From d4f0a226b59c62a5a72bc670501b692a20bec6b2 Mon Sep 17 00:00:00 2001 From: Jeremy5909 Date: Wed, 1 May 2024 12:47:40 -0700 Subject: [PATCH] depth of field --- src/camera.rs | 23 ++++++++++++++++++----- src/main.rs | 2 ++ src/vec3.rs | 10 ++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index e9b5dc5..0b29976 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -2,7 +2,7 @@ use std::{f64::INFINITY, io::stdout}; use rand::{thread_rng, Rng}; -use crate::{color::{write_color, Color}, hittable::{HitRecord, Hittable}, interval::Interval, ray::Ray, vec3::{cross, unit_vector, Point3, Vec3}}; +use crate::{color::{write_color, Color}, hittable::{HitRecord, Hittable}, interval::Interval, ray::Ray, vec3::{cross, random_in_unit_disk, unit_vector, Point3, Vec3}}; #[derive(Default)] pub struct Camera { pub aspect_ratio: f64, @@ -28,6 +28,11 @@ pub struct Camera { u: Vec3, v: Vec3, w: Vec3, + + pub defocus_angle: f64, + pub focus_dist: f64, + defocus_dist_u: Vec3, + defocus_dist_v: Vec3, } impl Camera { pub fn new(aspect_ratio: f64, image_width: i32) -> Self { @@ -38,6 +43,7 @@ impl Camera { fov: 90.0, look_at: Point3::new(0.0, 0.0, -1.0), vup: Vec3::new(0.0, 1.0, 0.0), + focus_dist: 10.0, ..Default::default()} } pub fn render(&mut self, world: &dyn Hittable) { @@ -64,10 +70,9 @@ impl Camera { self.pixel_samples_scale = 1.0 / self.samples_per_pixel as f64; self.center = self.look_from; - let focal_length = (self.look_from - self.look_at).length(); let theta = self.fov.to_radians(); let h = (theta/2.0).tan(); - let viewport_height = 2.0 * h * focal_length; + let viewport_height = 2.0 * h * self.focus_dist; let viewport_width = viewport_height * (self.image_width as f64/self.image_height as f64); self.w = unit_vector(&(self.look_from-self.look_at)); @@ -80,8 +85,12 @@ impl Camera { self.pixel_delta_u = viewport_u / self.image_width as f64; self.pixel_delta_v = viewport_v / self.image_height as f64; - let viewport_upper_left = self.center - (focal_length * self.w) - viewport_u/2.0 - viewport_v/2.0; + let viewport_upper_left = self.center - (self.focus_dist * self.w) - viewport_u/2.0 - viewport_v/2.0; self.pixel00_loc = viewport_upper_left + 0.5 * (self.pixel_delta_u + self.pixel_delta_v); + + let defocus_radius = self.focus_dist * (self.defocus_angle / 2.0).to_radians().tan(); + self.defocus_dist_u = self.u * defocus_radius; + self.defocus_dist_v = self.v * defocus_radius; } fn ray_color(r: &Ray, depth: i32, world: &dyn Hittable) -> Color { if depth <= 0 { @@ -106,7 +115,7 @@ impl Camera { let pixel_sample = self.pixel00_loc + ((i as f64 + offset.x()) * self.pixel_delta_u) + ((j as f64 + offset.y()) * self.pixel_delta_v); - let ray_origin = self.center; + let ray_origin = if self.defocus_angle <= 0.0 {self.center} else {self.defocus_disk_sample()}; let ray_direction = pixel_sample - ray_origin; Ray::new(ray_origin, ray_direction) } @@ -114,4 +123,8 @@ impl Camera { let mut rng = thread_rng(); Vec3::new(rng.gen_range(-0.5..0.5), rng.gen_range(-0.5..0.5), 0.0) } + fn defocus_disk_sample(&self) -> Point3 { + let p = random_in_unit_disk(); + self.center + (p[0] * self.defocus_dist_u) + (p[1] * self.defocus_dist_v) + } } diff --git a/src/main.rs b/src/main.rs index 53d9b8f..432c072 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,6 +43,8 @@ fn main() { cam.look_at = Point3::new(0.0, 0.0, -1.0); cam.vup = Vec3::new(0.0, 1.0, 0.0); cam.fov = 20.0; + cam.defocus_angle = 10.0; + cam.focus_dist = 3.4; cam.render(&world); } diff --git a/src/vec3.rs b/src/vec3.rs index 2e26f3b..f62655a 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -174,4 +174,14 @@ pub fn refract(uv: &Vec3, n: &Vec3, etai_over_etat: f64) -> Vec3 { let r_out_perp = etai_over_etat * (*uv + cos_theta * *n); let r_out_parallel = -(1.0 - r_out_perp.length_squared()).abs().sqrt() * *n; r_out_parallel + r_out_perp +} + +pub fn random_in_unit_disk() -> Vec3 { + let mut rng = thread_rng(); + loop { + let p = Vec3::new(rng.gen_range(-1.0 .. 1.0), rng.gen_range(-1.0 .. 1.0), 0.0); + if p.length_squared() < 1.0 { + return p; + } + } } \ No newline at end of file