diff options
author | Rosyid Haryadi <rosyid_haryadi@protonmail.com> | 2025-03-03 15:30:38 +0700 |
---|---|---|
committer | Rosyid Haryadi <rosyid_haryadi@protonmail.com> | 2025-03-03 15:30:38 +0700 |
commit | af169d990391d3301fc1993a65816612d29cb5e1 (patch) | |
tree | 368440c4cd773c74ecd1b16f41ac72bedf95081f | |
parent | d1909a30fbe458286e8a4cff86951773a3c64e68 (diff) |
upd camera focus
-rw-r--r-- | src/calculus.rs | 14 | ||||
-rw-r--r-- | src/camera.rs | 32 | ||||
-rw-r--r-- | src/common.rs | 3 |
3 files changed, 44 insertions, 5 deletions
diff --git a/src/calculus.rs b/src/calculus.rs index e59ae56..62253cf 100644 --- a/src/calculus.rs +++ b/src/calculus.rs @@ -132,6 +132,20 @@ pub mod calculus { let r_out_parallel = normal.scalar_mul(-1.0 * f); r_out_perp.add(&r_out_parallel) } + + pub fn random_in_unit_disk() -> Self { + let mut rng = rand::rng(); + loop { + let p = Vec3::new( + rng.random_range(-1.0..1.0), + rng.random_range(-1.0..1.0), + 0.0 + ); + if p.mag_sqr() < 1.0 { + return p; + } + } + } } pub struct Ray { diff --git a/src/camera.rs b/src/camera.rs index e58c13e..587e75c 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,5 +1,5 @@ use crate::calculus::calculus::{deg2rad, sample_square, Point3, Ray, Vec3}; -use crate::common::{get_image_height, Color, DisplayBuffer, Pixel, ASPECT_RATIO, IMG_WIDTH, LOOK_AT, LOOK_FROM, MAX_DEPTH, SAMPLES_PER_PIXEL, VFOV, VUP}; +use crate::common::{get_image_height, Color, DisplayBuffer, Pixel, ASPECT_RATIO, DEFOCUS_ANGLE, FOCUS_DIST, IMG_WIDTH, LOOK_AT, LOOK_FROM, MAX_DEPTH, SAMPLES_PER_PIXEL, VFOV, VUP}; use crate::interval::Interval; use crate::object::{HitRecord, Hittable, HittableList}; @@ -18,6 +18,10 @@ pub struct Camera { delta_pixel_v: Vec3, pixel_samples_scale: f32, max_depth: usize, + pub defocus_angle: f32, + pub focus_dist: f32, + pub defocus_disk_u: Vec3, + pub defocus_disk_v: Vec3, } impl Default for Camera { @@ -33,7 +37,7 @@ impl Default for Camera { let vup = VUP; let center = look_from; - let focal_length = look_from.sub(&look_at).mag(); + // let focal_length = look_from.sub(&look_at).mag(); let theta = deg2rad(vfov); let h = (theta / 2.0).tan(); @@ -44,7 +48,10 @@ impl Default for Camera { let samples_per_pixel = SAMPLES_PER_PIXEL; let pixel_samples_scale = 1.0 / samples_per_pixel as f32; - let viewport_height = 2.0 * h * focal_length; + let focus_dist = FOCUS_DIST; + let defocus_angle = DEFOCUS_ANGLE; + + let viewport_height = 2.0 * h * focus_dist; let viewport_width = viewport_height * (image_width as f32 / image_height as f32); let viewport_u = u.scalar_mul(viewport_width); @@ -54,13 +61,17 @@ impl Default for Camera { let delta_pixel_v = viewport_v.scalar_mul(1.0 / image_height as f32); let viewport_upper_left = center - .sub(&w.scalar_mul(focal_length)) + .sub(&w.scalar_mul(focus_dist)) .sub(&viewport_u.scalar_mul(0.5)) .sub(&viewport_v.scalar_mul(0.5)); let pixel_upper_left = viewport_upper_left.add( &delta_pixel_u.add(&delta_pixel_v).scalar_mul(0.5) ); + let defocus_radius = focus_dist * deg2rad(defocus_angle / 2.0).tan(); + let defocus_disk_u = u.scalar_mul(defocus_radius); + let defocus_disk_v = v.scalar_mul(defocus_radius); + let max_depth = MAX_DEPTH; Self { @@ -78,6 +89,10 @@ impl Default for Camera { look_from, look_at, vup, + defocus_angle, + focus_dist, + defocus_disk_u, + defocus_disk_v, } } } @@ -89,7 +104,7 @@ impl Camera { .add(&self.delta_pixel_u.scalar_mul(i as f32 + offset.x)) .add(&self.delta_pixel_v.scalar_mul(j as f32 + offset.y)); - 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.sub(&ray_origin); Ray { @@ -98,6 +113,13 @@ impl Camera { } } + fn defocus_disk_sample(&self) -> Point3 { + let p = Vec3::random_in_unit_disk(); + self.center + .add(&self.defocus_disk_u.scalar_mul(p.x)) + .add(&self.defocus_disk_v.scalar_mul(p.y)) + } + fn ray_color(&self, ray: &Ray, world: &HittableList, depth: usize) -> Color { if depth <= 0 { return Color::new(0.0, 0.0, 0.0); diff --git a/src/common.rs b/src/common.rs index 69f9a48..3f111ec 100644 --- a/src/common.rs +++ b/src/common.rs @@ -18,6 +18,9 @@ pub const LOOK_FROM: Point3 = Point3 { x: -2.0, y: 2.0, z: 1.0 }; pub const LOOK_AT: Point3 = Point3 { x: 0.0, y: 0.0, z: -1.0 }; pub const VUP: Vec3 = Vec3 { x: 0.0, y: 1.0, z: 0.0 }; +pub const DEFOCUS_ANGLE: f32 = 10.0; +pub const FOCUS_DIST: f32 = 4.0; + pub const fn get_image_height(image_width: usize, aspect_ratio: f32) -> usize { let image_height = (image_width as f32 / aspect_ratio) as usize; if image_width < 1 { 1 } else { image_height } |