summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRosyid Haryadi <rosyid_haryadi@protonmail.com>2025-03-03 15:30:38 +0700
committerRosyid Haryadi <rosyid_haryadi@protonmail.com>2025-03-03 15:30:38 +0700
commitaf169d990391d3301fc1993a65816612d29cb5e1 (patch)
tree368440c4cd773c74ecd1b16f41ac72bedf95081f
parentd1909a30fbe458286e8a4cff86951773a3c64e68 (diff)
upd camera focus
-rw-r--r--src/calculus.rs14
-rw-r--r--src/camera.rs32
-rw-r--r--src/common.rs3
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 }