From ffd00cf2d8eb77b0b96b258629addab4c591fe14 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 25 Jan 2023 13:53:19 -0800 Subject: [PATCH] add shadows --- Makefile | 3 +- main-saturn.cpp | 1 + raytracing.cpp | 105 ++++++++++++++++++++++++++++++------------------ 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 8ece37a..f3b0496 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ CFLAGS = -Isaturn -Imath -OPT = -O3 +OPT = -O1 + LIBGCC = $(shell $(CC) -print-file-name=libgcc.a) all: raytracing.iso diff --git a/main-saturn.cpp b/main-saturn.cpp index 0487605..8b5fba8 100644 --- a/main-saturn.cpp +++ b/main-saturn.cpp @@ -8,6 +8,7 @@ #include "fp.hpp" #include "raytracing.hpp" +constexpr inline fp16_16 clamp(fp16_16 const& n) { return (n > fp16_16(1) ? fp16_16(1) : (n < fp16_16(0) ? fp16_16(0) : n)); diff --git a/raytracing.cpp b/raytracing.cpp index 61f8c00..29c0e84 100644 --- a/raytracing.cpp +++ b/raytracing.cpp @@ -100,44 +100,7 @@ struct t1_t2 { fp16_16 t2; }; -fp16_16 compute_lighting(const vec3& point, const vec3& normal, - const vec3& viewer, fp16_16 specular) -{ - fp16_16 intensity{0}; - - for (int i = 0; i < 3; i++) { - const light& light = scene.lights[i]; - if (light.type == light_type::ambient) { - intensity += light.intensity; - } else { - vec3 light_vector; - if (light.type == light_type::point) { - light_vector = light.position - point; - } else { - light_vector = light.direction; - } - - // diffuse - auto n_dot_l = dot(normal, light_vector); - if (n_dot_l > fp16_16(0)) { - intensity += light.intensity * n_dot_l * (fp16_16(1) / length(light_vector)); - } - - // specular - if (specular > fp16_16(0)) { - auto reflected = normal * fp16_16(2) * dot(normal, light_vector) - light_vector; - auto r_dot_v = dot(reflected, viewer); - if (r_dot_v > fp16_16(0)) { - auto base = r_dot_v / (length(reflected) * length(viewer)); - intensity += light.intensity * pow(base, specular); - } - } - } - } - return intensity; -} - -t1_t2 intersect_ray_sphere(const vec3& origin, const vec3& direction, const sphere& sphere) +inline t1_t2 intersect_ray_sphere(const vec3& origin, const vec3& direction, const sphere& sphere) { fp16_16 r = sphere.radius; vec3 CO = origin - sphere.center; @@ -159,7 +122,12 @@ t1_t2 intersect_ray_sphere(const vec3& origin, const vec3& direction, const sphe } } -static vec3 trace_ray +struct t_sphere { + fp16_16 closest_t; + const sphere * closest_sphere; +}; + +inline t_sphere closest_intersection ( const vec3& origin, const vec3& direction, @@ -169,6 +137,7 @@ static vec3 trace_ray { fp16_16 closest_t = fp_limits::max(); const sphere * closest_sphere = nullptr; + for (int i = 0; i < 4; i++) { auto& sphere = scene.spheres[i]; auto [t1, t2] = intersect_ray_sphere(origin, direction, sphere); @@ -181,6 +150,64 @@ static vec3 trace_ray closest_sphere = &sphere; } } + + return {closest_t, closest_sphere}; +} + +fp16_16 compute_lighting(const vec3& point, const vec3& normal, + const vec3& viewer, fp16_16 specular) +{ + fp16_16 intensity{0}; + + for (int i = 0; i < 3; i++) { + const light& light = scene.lights[i]; + if (light.type == light_type::ambient) { + intensity += light.intensity; + } else { + vec3 light_vector; + fp16_16 t_max(0); + if (light.type == light_type::point) { + light_vector = light.position - point; + t_max = fp16_16(1); + } else { + light_vector = light.direction; + t_max = fp_limits::max(); + } + + constexpr fp16_16 t_min = fp16_16(128, fp_raw_tag{}); + auto [shadow_t, shadow_sphere] = closest_intersection(point, light_vector, t_min, t_max); + if (shadow_sphere != nullptr) + continue; + + // diffuse + auto n_dot_l = dot(normal, light_vector); + if (n_dot_l > fp16_16(0)) { + intensity += light.intensity * n_dot_l * (fp16_16(1) / length(light_vector)); + } + + // specular + if (specular > fp16_16(0)) { + auto reflected = normal * fp16_16(2) * dot(normal, light_vector) - light_vector; + auto r_dot_v = dot(reflected, viewer); + if (r_dot_v > fp16_16(0)) { + auto base = r_dot_v / (length(reflected) * length(viewer)); + intensity += light.intensity * pow(base, specular); + } + } + } + } + return intensity; +} + +static vec3 trace_ray +( + const vec3& origin, + const vec3& direction, + const fp16_16 t_min, + const fp16_16 t_max +) +{ + auto [closest_t, closest_sphere] = closest_intersection(origin, direction, t_min, t_max); if (closest_sphere == nullptr) { return vec3(0, 0, 0); } else {