Feat: Simulate depth-of-field
And with that, I'm on to the final render. Chapter 12 closed!
This commit is contained in:
@@ -14,15 +14,28 @@ use crate::vec3::Vec3;
|
|||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
use crate::degrees_to_radians;
|
use crate::degrees_to_radians;
|
||||||
|
|
||||||
|
use rand::rngs::SmallRng;
|
||||||
|
use rand::distributions::Uniform;
|
||||||
|
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
pub origin: Vec3,
|
origin: Vec3,
|
||||||
pub lower_left_corner: Vec3,
|
lower_left_corner: Vec3,
|
||||||
pub horizontal: Vec3,
|
horizontal: Vec3,
|
||||||
pub vertical: Vec3,
|
vertical: Vec3,
|
||||||
|
u: Vec3, v: Vec3, w: Vec3,
|
||||||
|
lens_radius: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
pub fn new(lookfrom: Vec3, lookat: Vec3, vup: Vec3, vfov: f32, aspect_ratio: f32) -> Camera {
|
pub fn new(
|
||||||
|
lookfrom: Vec3,
|
||||||
|
lookat: Vec3,
|
||||||
|
vup: Vec3,
|
||||||
|
vfov: f32,
|
||||||
|
aspect_ratio: f32,
|
||||||
|
aperture: f32,
|
||||||
|
focus_dist: f32
|
||||||
|
) -> Camera {
|
||||||
let theta = degrees_to_radians(vfov);
|
let theta = degrees_to_radians(vfov);
|
||||||
let h = (theta / 2.0).tan();
|
let h = (theta / 2.0).tan();
|
||||||
let vp_height = 2.0 * h;
|
let vp_height = 2.0 * h;
|
||||||
@@ -33,25 +46,30 @@ impl Camera {
|
|||||||
let v = Vec3::cross(w, u);
|
let v = Vec3::cross(w, u);
|
||||||
|
|
||||||
let orig = lookfrom;
|
let orig = lookfrom;
|
||||||
let horiz = u * vp_width;
|
let horiz = u * vp_width * focus_dist;
|
||||||
let verti = v * vp_height;
|
let verti = v * vp_height * focus_dist;
|
||||||
let lower_left_corner = orig - horiz / 2.0 - verti / 2.0 - w;
|
let lower_left_corner = orig - horiz / 2.0 - verti / 2.0 - w * focus_dist;
|
||||||
|
|
||||||
Camera{
|
Camera{
|
||||||
origin: orig,
|
origin: orig,
|
||||||
lower_left_corner,
|
lower_left_corner,
|
||||||
horizontal: horiz,
|
horizontal: horiz,
|
||||||
vertical: verti,
|
vertical: verti,
|
||||||
|
u, v, w,
|
||||||
|
lens_radius: aperture / 2.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ray(&self, s: f32, t: f32) -> Ray {
|
pub fn get_ray(&self, s: f32, t: f32, srng: &mut SmallRng, distrib: Uniform<f32>) -> Ray {
|
||||||
|
let rd = Vec3::rand_in_unit_disk(srng, distrib) * self.lens_radius;
|
||||||
|
let offset = self.u * rd.x + self.v * rd.y;
|
||||||
|
|
||||||
let dir = self.lower_left_corner
|
let dir = self.lower_left_corner
|
||||||
+ self.horizontal * s
|
+ self.horizontal * s
|
||||||
+ self.vertical * t
|
+ self.vertical * t
|
||||||
- self.origin;
|
- self.origin - offset;
|
||||||
Ray{
|
Ray{
|
||||||
orig: self.origin,
|
orig: self.origin + offset,
|
||||||
dir,
|
dir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/main.rs
21
src/main.rs
@@ -25,8 +25,8 @@ fn main() {
|
|||||||
// image
|
// image
|
||||||
let aspect_ratio = 16.0 / 9.0;
|
let aspect_ratio = 16.0 / 9.0;
|
||||||
let image = (
|
let image = (
|
||||||
400,
|
1920,
|
||||||
(400.0 / aspect_ratio) as i32
|
(1920.0 / aspect_ratio) as i32
|
||||||
);
|
);
|
||||||
let samples_per_pixel = 100;
|
let samples_per_pixel = 100;
|
||||||
let max_depth = 50;
|
let max_depth = 50;
|
||||||
@@ -92,12 +92,19 @@ fn main() {
|
|||||||
|
|
||||||
// camera
|
// camera
|
||||||
|
|
||||||
|
let lookfrom = Vec3::new(3.0, 3.0, 2.0);
|
||||||
|
let lookat = Vec3::new(0.0, 0.0, -1.0);
|
||||||
|
let vup = Vec3::new(0.0, 1.0, 0.0);
|
||||||
|
let dist_to_focus = (lookfrom - lookat).length();
|
||||||
|
let aperture = 2.0;
|
||||||
let cam = Camera::new(
|
let cam = Camera::new(
|
||||||
Vec3::new(-2.0, 2.0, 1.0),
|
lookfrom,
|
||||||
Vec3::new(0.0, 0.0, -1.0),
|
lookat,
|
||||||
Vec3::new(0.0, 1.0, 0.0),
|
vup,
|
||||||
20.0,
|
20.0,
|
||||||
aspect_ratio
|
aspect_ratio,
|
||||||
|
aperture,
|
||||||
|
dist_to_focus
|
||||||
);
|
);
|
||||||
|
|
||||||
// render
|
// render
|
||||||
@@ -112,7 +119,7 @@ fn main() {
|
|||||||
for _ in 0..samples_per_pixel {
|
for _ in 0..samples_per_pixel {
|
||||||
let u = ((x as f32) + small_rng.sample(distrib_zero_one)) / ((image.0 - 1) as f32);
|
let u = ((x as f32) + small_rng.sample(distrib_zero_one)) / ((image.0 - 1) as f32);
|
||||||
let v = ((y as f32) + small_rng.sample(distrib_zero_one)) / ((image.1 - 1) as f32);
|
let v = ((y as f32) + small_rng.sample(distrib_zero_one)) / ((image.1 - 1) as f32);
|
||||||
let ray = cam.get_ray(u, v);
|
let ray = cam.get_ray(u, v, &mut small_rng, distrib_plusminus_one);
|
||||||
color+= ray_color(ray, &world, max_depth, &mut small_rng, distrib_plusminus_one);
|
color+= ray_color(ray, &world, max_depth, &mut small_rng, distrib_plusminus_one);
|
||||||
}
|
}
|
||||||
println!("{}", color.print_ppm(samples_per_pixel));
|
println!("{}", color.print_ppm(samples_per_pixel));
|
||||||
|
|||||||
12
src/vec3.rs
12
src/vec3.rs
@@ -61,6 +61,18 @@ impl Vec3{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rand_in_unit_disk(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
||||||
|
loop {
|
||||||
|
let p = Vec3 {
|
||||||
|
x: srng.sample(distrib),
|
||||||
|
y: srng.sample(distrib),
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
if p.length_squared() >= 1.0 { continue; }
|
||||||
|
else { return p; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rand_unit_vector(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
pub fn rand_unit_vector(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
||||||
return Vec3::as_unit(Vec3::rand_in_unit_sphere(srng, distrib));
|
return Vec3::as_unit(Vec3::rand_in_unit_sphere(srng, distrib));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user