From 482a3bf1965ccbb2fabc82a2635ae60589244e7d Mon Sep 17 00:00:00 2001 From: Jean-Michel Gorius Date: Fri, 11 Nov 2022 22:58:22 +0100 Subject: [PATCH] Add defocus blur --- camera.c | 25 +++++++++++++++++-------- camera.h | 5 ++++- main.c | 11 +++++++++-- vec3.c | 16 +++++++++++++--- vec3.h | 1 + 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/camera.c b/camera.c index 504a466..9e3ec0b 100644 --- a/camera.c +++ b/camera.c @@ -6,29 +6,38 @@ #include void camera_init(Camera *camera, Point3 look_from, Point3 look_at, Vec3 up, - double vertical_fov, double aspect_ratio) { + double vertical_fov, double aspect_ratio, double aperture, + double focus_distance) { double theta = degrees_to_radians(vertical_fov); double h = tan(theta / 2.0); double viewport_height = 2.0 * h; double viewport_width = aspect_ratio * viewport_height; - Vec3 w = vec3_normalize(point3_sub(look_from, look_at)); - Vec3 u = vec3_normalize(vec3_cross(up, w)); - Vec3 v = vec3_cross(w, u); + camera->w = vec3_normalize(point3_sub(look_from, look_at)); + camera->u = vec3_normalize(vec3_cross(up, camera->w)); + camera->v = vec3_cross(camera->w, camera->u); camera->origin = look_from; - camera->horizontal = vec3_mul(viewport_width, u); - camera->vertical = vec3_mul(viewport_height, v); + camera->horizontal = vec3_mul(focus_distance * viewport_width, camera->u); + camera->vertical = vec3_mul(focus_distance * viewport_height, camera->v); Vec3 offset = vec3_add(vec3_div(camera->horizontal, 2), vec3_div(camera->vertical, 2)); - offset = vec3_add(offset, w); + offset = vec3_add(offset, vec3_mul(focus_distance, camera->w)); camera->lower_left_corner = point3_add(camera->origin, vec3_neg(offset)); + + camera->lens_radius = aperture / 2.0; } Ray camera_get_ray(const Camera *camera, double s, double t) { + Vec3 rd = vec3_mul(camera->lens_radius, vec3_random_in_unit_disk()); + Vec3 offset = vec3_add(vec3_mul(rd.x, camera->u), vec3_mul(rd.y, camera->v)); + Point3 screen_point = point3_add( camera->lower_left_corner, vec3_add(vec3_mul(s, camera->horizontal), vec3_mul(t, camera->vertical))); Vec3 direction = point3_sub(screen_point, camera->origin); - return (Ray){camera->origin, direction}; + return (Ray){ + point3_add(camera->origin, offset), + vec3_sub(direction, offset), + }; } diff --git a/camera.h b/camera.h index b839bc5..0607f10 100644 --- a/camera.h +++ b/camera.h @@ -10,10 +10,13 @@ typedef struct Camera { Point3 lower_left_corner; Vec3 horizontal; Vec3 vertical; + Vec3 u, v, w; + double lens_radius; } Camera; void camera_init(Camera *camera, Point3 look_from, Point3 look_at, Vec3 up, - double vertical_fov, double aspect_ratio); + double vertical_fov, double aspect_ratio, double aperture, + double focus_distance); Ray camera_get_ray(const Camera *camera, double s, double t); diff --git a/main.c b/main.c index 7b2db58..4abda6b 100644 --- a/main.c +++ b/main.c @@ -90,9 +90,16 @@ int main(void) { hittable_list_add(&world, (const Hittable *)&sphere_right); /* Camera */ + + Point3 look_from = {3.0, 3.0, 2.0}; + Point3 look_at = {0.0, 0.0, -1.0}; + Vec3 up = {0.0, 1.0, 0.0}; + double dist_to_focus = vec3_length(point3_sub(look_from, look_at)); + double aperture = 2.0; + Camera camera; - camera_init(&camera, (Point3){-2.0, 2.0, 1.0}, (Point3){0.0, 0.0, -1.0}, - (Vec3){0.0, 1.0, 0.0}, 20, aspect_ratio); + camera_init(&camera, look_from, look_at, up, 20, aspect_ratio, aperture, + dist_to_focus); printf("P3\n%u %u\n255\n", image_width, image_height); diff --git a/vec3.c b/vec3.c index 318c4ec..aad18a4 100644 --- a/vec3.c +++ b/vec3.c @@ -52,9 +52,19 @@ Vec3 vec3_random_in_range(double min, double max) { } Vec3 vec3_random_in_unit_sphere(void) { - while (1) { - Vec3 result = vec3_random_in_range(-1, 1); - if (vec3_length2(result) >= 1) + while (true) { + Vec3 result = vec3_random_in_range(-1.0, 1.0); + if (vec3_length2(result) >= 1.0) + continue; + return result; + } +} + +Vec3 vec3_random_in_unit_disk(void) { + while (true) { + Vec3 result = (Vec3){random_double_in_range(-1.0, 1.0), + random_double_in_range(-1.0, 1.0), 0.0}; + if (vec3_length2(result) >= 1.0) continue; return result; } diff --git a/vec3.h b/vec3.h index dcea3f0..9cc5f89 100644 --- a/vec3.h +++ b/vec3.h @@ -24,6 +24,7 @@ Vec3 vec3_cross(Vec3 v1, Vec3 v2); Vec3 vec3_random(void); Vec3 vec3_random_in_range(double min, double max); Vec3 vec3_random_in_unit_sphere(void); +Vec3 vec3_random_in_unit_disk(void); Vec3 vec3_random_unit_vector(void); bool vec3_is_near_zero(Vec3 v);