Refactor trace_ray function

This commit is contained in:
Abdelrahman Said 2024-02-04 00:11:20 +00:00
parent bfdea0fd0c
commit 1f5568b63e

View File

@ -46,10 +46,21 @@ typedef struct {
f32 t2; f32 t2;
} solutions_t; } solutions_t;
solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction, typedef struct {
sphere_t sphere); 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, colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
const scene_t *scene, colour_t default_colour); 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, f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
vec3f_t view_vector, f32 specular_exponent, vec3f_t view_vector, f32 specular_exponent,
const scene_t *scene); const scene_t *scene);
@ -167,28 +178,37 @@ i32 main(i32 argc, char *argv[]) {
return EXIT_SUCCESS; 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, colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
const scene_t *scene, colour_t default_colour) { 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; f32 closest_t = INFINITY;
sphere_t *closest_sphere = NULL; 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 (intersection_t){closest_t, closest_sphere};
return default_colour;
} }
vec3f_t position = f32 calculate_lighting_for_intersection(vec3f_t origin, vec3f_t direction,
vec_add(vec3f_t, origin, vec_mul_num(vec3f_t, direction, closest_t)); 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, surface_normal = vec_div_num(vec3f_t, surface_normal,
vec_magnitude(vec3f_t, surface_normal)); vec_magnitude(vec3f_t, surface_normal));
vec3f_t view_vector = vec_mul_num(vec3f_t, direction, -1.0f); vec3f_t view_vector = vec_mul_num(vec3f_t, direction, -1.0f);
f32 light = compute_lighting(position, surface_normal, view_vector, return compute_lighting(position, surface_normal, view_vector,
closest_sphere->specular, scene); intersection.closest_sphere->specular, scene);
}
f32 r = (f32)(closest_sphere->colour.rgba.r) * light; solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
r = clamp(r, 0.0f, (f32)UINT8_MAX); sphere_t sphere) {
f32 g = (f32)(closest_sphere->colour.rgba.g) * light; f32 r = sphere.radius;
g = clamp(g, 0.0f, (f32)UINT8_MAX); vec3f_t CO = vec_sub(vec3f_t, origin, sphere.centre);
f32 b = (f32)(closest_sphere->colour.rgba.b) * light;
b = clamp(b, 0.0f, (f32)UINT8_MAX);
return (colour_t){ f32 a = vec_dot(vec3f_t, direction, direction);
.rgba.r = (u8)r, f32 b = 2.0f * vec_dot(vec3f_t, CO, direction);
.rgba.g = (u8)g, f32 c = vec_dot(vec3f_t, CO, CO) - r * r;
.rgba.b = (u8)b,
.rgba.a = closest_sphere->colour.rgba.a, 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, f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,