Skip to content

Commit 9046a7f

Browse files
committed
2§2. Motion Blur
1 parent 9c8d3db commit 9046a7f

7 files changed

Lines changed: 87 additions & 31 deletions

File tree

src/camera.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use indicatif::{ParallelProgressIterator, ProgressIterator};
22
use rayon::prelude::*;
33

44
use crate::{
5-
float::{Fl, lerp, random},
5+
float::{lerp, random, Fl},
66
hittable::{Hittable, HittableObject},
77
interval::Interval,
88
material::Material,
@@ -130,7 +130,9 @@ impl Camera {
130130
self.sample_defocus_disk()
131131
};
132132

133-
Ray::new(origin, pixel_sample - origin, x, y)
133+
Ray::new(origin, pixel_sample - origin)
134+
.at_time(random())
135+
.for_pixel((x, y))
134136
}
135137

136138
fn sample_square() -> Vec3 {

src/dielectric.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ impl Material for DielectricMaterial {
4343

4444
Some(ScatterRecord {
4545
attenuation: Color::new(1., 1., 1.),
46-
scattered: Ray::new(rec.p, direction, r_in.pixel_x(), r_in.pixel_y()),
46+
scattered: Ray::new(rec.p, direction)
47+
.at_time_of(r_in)
48+
.for_pixel_of(r_in),
4749
})
4850
}
4951
}

src/lambertian.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ impl Material for LambertianMaterial {
2626

2727
Some(ScatterRecord {
2828
attenuation: self.albedo,
29-
scattered: Ray::new(rec.p, scatter_direction, r_in.pixel_x(), r_in.pixel_y()),
29+
scattered: Ray::new(rec.p, scatter_direction)
30+
.at_time_of(r_in)
31+
.for_pixel_of(r_in),
3032
})
3133
}
3234
}

src/main.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,17 @@ pub fn main() {
3131
for a in -11..11 {
3232
for b in -11..11 {
3333
let choose_mat = random();
34-
let center = Pos3::new(
35-
(a as Fl) + 0.9 * random(),
36-
0.2,
37-
(b as Fl) + 0.9 * random(),
38-
);
34+
let center = Pos3::new((a as Fl) + 0.9 * random(), 0.2, (b as Fl) + 0.9 * random());
3935

4036
if choose_mat < 0.8 {
4137
world.add(
42-
Sphere::new(center, 0.2, LambertianMaterial::new(Color::random()).into())
43-
.into(),
38+
Sphere::new_moving(
39+
center,
40+
center + Vec3::new(0., random() * 0.5, 0.),
41+
0.2,
42+
LambertianMaterial::new(Color::random()).into(),
43+
)
44+
.into(),
4445
);
4546
} else if choose_mat < 0.95 {
4647
world.add(
@@ -90,8 +91,8 @@ pub fn main() {
9091

9192
let camera = Camera::new(CameraOptions {
9293
aspect_ratio: 16. / 9.,
93-
image_width: 1200,
94-
samples_per_pixel: 50,
94+
image_width: 400,
95+
samples_per_pixel: 100,
9596
max_depth: 50,
9697
v_fov: 20.,
9798
look_from: Pos3::new(13., 2., 3.),

src/metal.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use crate::{
2-
float::Fl, hittable::HitRecord, material::{Material, ScatterRecord}, ray::Ray, vec3::{Color, Vec3}
2+
float::Fl,
3+
hittable::HitRecord,
4+
material::{Material, ScatterRecord},
5+
ray::Ray,
6+
vec3::{Color, Vec3},
37
};
48

59
#[derive(Debug, Default, PartialEq, Clone, Copy)]
@@ -18,7 +22,9 @@ impl Material for MetalMaterial {
1822
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> Option<ScatterRecord> {
1923
let reflected =
2024
r_in.direction().reflect(&rec.normal) + Vec3::random_normalized() * self.fuzz;
21-
let scattered = Ray::new(rec.p, reflected, r_in.pixel_x(), r_in.pixel_y());
25+
let scattered = Ray::new(rec.p, reflected)
26+
.at_time_of(r_in)
27+
.for_pixel_of(r_in);
2228

2329
(scattered.direction().dot(&rec.normal) > 0.).then_some(ScatterRecord {
2430
attenuation: self.albedo,

src/ray.rs

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ use crate::{float::Fl, vec3::{Pos3, Vec3}};
44
pub struct Ray {
55
origin: Pos3,
66
direction: Vec3,
7-
pixel_x: usize,
8-
pixel_y: usize,
7+
time: Fl,
8+
pixel: Option<(usize, usize)>,
99
}
1010

1111
impl Ray {
12-
pub const fn new(origin: Pos3, direction: Vec3, pixel_x: usize, pixel_y: usize) -> Self {
12+
pub const fn new(origin: Pos3, direction: Vec3) -> Self {
1313
Self {
1414
origin,
1515
direction,
16-
pixel_x,
17-
pixel_y,
16+
time: 0.,
17+
pixel: None,
1818
}
1919
}
2020

@@ -26,16 +26,50 @@ impl Ray {
2626
&self.direction
2727
}
2828

29-
pub const fn pixel_x(&self) -> usize {
30-
self.pixel_x
29+
pub const fn at_time(&self, time: Fl) -> Self {
30+
Self {
31+
direction: self.direction,
32+
origin: self.origin,
33+
time,
34+
pixel: self.pixel,
35+
}
36+
}
37+
38+
pub const fn at_time_of(&self, other: &Self) -> Self {
39+
self.at_time(other.time)
40+
}
41+
42+
pub fn at_time_mut(&mut self, time: Fl) {
43+
self.time = time;
44+
}
45+
46+
pub const fn time(&self) -> Fl {
47+
self.time
48+
}
49+
50+
pub const fn for_pixel(&self, pixel: (usize, usize)) -> Self {
51+
Self {
52+
direction: self.direction,
53+
origin: self.origin,
54+
time: self.time,
55+
pixel: Some(pixel),
56+
}
57+
}
58+
59+
pub const fn for_pixel_of(&self, other: &Self) -> Self {
60+
if let Some(p) = other.pixel {
61+
self.for_pixel(p)
62+
} else {
63+
*self
64+
}
3165
}
3266

33-
pub const fn pixel_y(&self) -> usize {
34-
self.pixel_y
67+
pub fn for_pixel_mut(&mut self, pixel: (usize, usize)) {
68+
self.pixel = Some(pixel);
3569
}
3670

37-
pub const fn is_pixel_at(&self, x: usize, y: usize) -> bool {
38-
self.pixel_x == x && self.pixel_y == y
71+
pub const fn pixel(&self) -> Option<(usize, usize)> {
72+
self.pixel
3973
}
4074

4175
pub fn at(&self, t: Fl) -> Pos3 {

src/sphere.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,33 @@ use crate::{
44

55
#[derive(Debug, Clone)]
66
pub struct Sphere {
7-
center: Pos3,
7+
center: Ray,
88
radius: Fl,
99
mat: MaterialObject,
1010
}
1111

1212
impl Sphere {
1313
pub fn new(center: Pos3, radius: Fl, mat: MaterialObject) -> Self {
1414
Self {
15-
center,
16-
radius,
15+
center: Ray::new(center, Pos3::default()),
16+
radius: radius.max(0.),
17+
mat,
18+
}
19+
}
20+
21+
pub fn new_moving(center1: Pos3, center2: Pos3, radius: Fl, mat: MaterialObject) -> Self {
22+
Self {
23+
center: Ray::new(center1, center2 - center1),
24+
radius: radius.max(0.),
1725
mat,
1826
}
1927
}
2028
}
2129

2230
impl Hittable for Sphere {
2331
fn hit(&self, r: &Ray, ray_t: Interval) -> Option<HitRecord> {
24-
let oc = &self.center - r.origin();
32+
let current_center = self.center.at(r.time());
33+
let oc = &current_center - r.origin();
2534
let a = r.direction().squared_abs();
2635
let h = r.direction().dot(&oc);
2736
let c = oc.squared_abs() - self.radius * self.radius;
@@ -44,7 +53,7 @@ impl Hittable for Sphere {
4453

4554
let t = root;
4655
let p = r.at(t);
47-
let outward_normal = (p - self.center) / self.radius;
56+
let outward_normal = (p - current_center) / self.radius;
4857

4958
Some(HitRecord::new(t, p, self.mat.clone(), r, outward_normal))
5059
}

0 commit comments

Comments
 (0)