From 1f5568b63e5e1b2fec5ffd978c244b95de72e2d3 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 4 Feb 2024 00:11:20 +0000 Subject: [PATCH] Refactor trace_ray function --- src/raytracer/main.c | 113 +++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/src/raytracer/main.c b/src/raytracer/main.c index 5405521..0e305ad 100644 --- a/src/raytracer/main.c +++ b/src/raytracer/main.c @@ -46,10 +46,21 @@ typedef struct { f32 t2; } solutions_t; -solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction, - sphere_t sphere); +typedef struct { + f32 closest_t; + sphere_t *closest_sphere; +} intersection_t; + colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max, const scene_t *scene, colour_t default_colour); +intersection_t find_closest_intersection(vec3f_t origin, vec3f_t direction, + f32 t_min, f32 t_max, + const scene_t *scene); +f32 calculate_lighting_for_intersection(vec3f_t origin, vec3f_t direction, + intersection_t intersection, + const scene_t *scene); +solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction, + sphere_t sphere); f32 compute_lighting(vec3f_t position, vec3f_t surface_normal, vec3f_t view_vector, f32 specular_exponent, const scene_t *scene); @@ -167,28 +178,37 @@ i32 main(i32 argc, char *argv[]) { return EXIT_SUCCESS; } -solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction, - sphere_t sphere) { - f32 r = sphere.radius; - vec3f_t CO = vec_sub(vec3f_t, origin, sphere.centre); - - f32 a = vec_dot(vec3f_t, direction, direction); - f32 b = 2.0f * vec_dot(vec3f_t, CO, direction); - f32 c = vec_dot(vec3f_t, CO, CO) - r * r; - - f32 discriminant = b * b - 4 * a * c; - if (discriminant < 0) { - return (solutions_t){INFINITY, INFINITY}; - } - - f32 t1 = (-b + sqrtf(discriminant)) / (2 * a); - f32 t2 = (-b - sqrtf(discriminant)) / (2 * a); - - return (solutions_t){t1, t2}; -} - colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max, const scene_t *scene, colour_t default_colour) { + + intersection_t intersection = + find_closest_intersection(origin, direction, t_min, t_max, scene); + + if (!intersection.closest_sphere) { + return default_colour; + } + + f32 light = calculate_lighting_for_intersection(origin, direction, + intersection, scene); + + f32 r = (f32)(intersection.closest_sphere->colour.rgba.r) * light; + r = clamp(r, 0.0f, (f32)UINT8_MAX); + f32 g = (f32)(intersection.closest_sphere->colour.rgba.g) * light; + g = clamp(g, 0.0f, (f32)UINT8_MAX); + f32 b = (f32)(intersection.closest_sphere->colour.rgba.b) * light; + b = clamp(b, 0.0f, (f32)UINT8_MAX); + + return (colour_t){ + .rgba.r = (u8)r, + .rgba.g = (u8)g, + .rgba.b = (u8)b, + .rgba.a = intersection.closest_sphere->colour.rgba.a, + }; +} + +intersection_t find_closest_intersection(vec3f_t origin, vec3f_t direction, + f32 t_min, f32 t_max, + const scene_t *scene) { f32 closest_t = INFINITY; sphere_t *closest_sphere = NULL; @@ -209,35 +229,44 @@ colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max, } } - if (!closest_sphere) { - return default_colour; - } + return (intersection_t){closest_t, closest_sphere}; +} - vec3f_t position = - vec_add(vec3f_t, origin, vec_mul_num(vec3f_t, direction, closest_t)); +f32 calculate_lighting_for_intersection(vec3f_t origin, vec3f_t direction, + intersection_t intersection, + const scene_t *scene) { + vec3f_t position = vec_add( + vec3f_t, origin, vec_mul_num(vec3f_t, direction, intersection.closest_t)); - vec3f_t surface_normal = vec_sub(vec3f_t, position, closest_sphere->centre); + vec3f_t surface_normal = + vec_sub(vec3f_t, position, intersection.closest_sphere->centre); surface_normal = vec_div_num(vec3f_t, surface_normal, vec_magnitude(vec3f_t, surface_normal)); vec3f_t view_vector = vec_mul_num(vec3f_t, direction, -1.0f); - f32 light = compute_lighting(position, surface_normal, view_vector, - closest_sphere->specular, scene); + return compute_lighting(position, surface_normal, view_vector, + intersection.closest_sphere->specular, scene); +} - f32 r = (f32)(closest_sphere->colour.rgba.r) * light; - r = clamp(r, 0.0f, (f32)UINT8_MAX); - f32 g = (f32)(closest_sphere->colour.rgba.g) * light; - g = clamp(g, 0.0f, (f32)UINT8_MAX); - f32 b = (f32)(closest_sphere->colour.rgba.b) * light; - b = clamp(b, 0.0f, (f32)UINT8_MAX); +solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction, + sphere_t sphere) { + f32 r = sphere.radius; + vec3f_t CO = vec_sub(vec3f_t, origin, sphere.centre); - return (colour_t){ - .rgba.r = (u8)r, - .rgba.g = (u8)g, - .rgba.b = (u8)b, - .rgba.a = closest_sphere->colour.rgba.a, - }; + f32 a = vec_dot(vec3f_t, direction, direction); + f32 b = 2.0f * vec_dot(vec3f_t, CO, direction); + f32 c = vec_dot(vec3f_t, CO, CO) - r * r; + + f32 discriminant = b * b - 4 * a * c; + if (discriminant < 0) { + return (solutions_t){INFINITY, INFINITY}; + } + + f32 t1 = (-b + sqrtf(discriminant)) / (2 * a); + f32 t2 = (-b - sqrtf(discriminant)) / (2 * a); + + return (solutions_t){t1, t2}; } f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,