@@ 1,14 1,26 @@
-use crate::{cross, degrees_to_radians, unit_vector, Point3, Ray, Vec3};
+use crate::{cross, degrees_to_radians, random_in_unit_disk, unit_vector, Point3, Ray, Vec3};
pub struct Camera {
origin: Point3,
lower_left_corner: Point3,
horizontal: Vec3,
vertical: Vec3,
+ u: Vec3,
+ v: Vec3,
+ w: Vec3,
+ lens_radius: f64,
}
impl Camera {
- pub fn new(lookfrom: Point3, lookat: Point3, vup: Vec3, vfov: f64, aspect_ratio: f64) -> Self {
+ pub fn new(
+ lookfrom: Point3,
+ lookat: Point3,
+ vup: Vec3,
+ vfov: f64,
+ aspect_ratio: f64,
+ aperture: f64,
+ focus_dist: f64,
+ ) -> Self {
let theta = degrees_to_radians(vfov);
let h = (theta / 2.0).tan();
let viewport_height = 2.0 * h;
@@ 18,21 30,32 @@ impl Camera {
let u = unit_vector(cross(&vup, &w));
let v = cross(&w, &u);
let origin = lookfrom;
- let horizontal = viewport_width * u;
- let vertical = viewport_height * v;
- let lower_left_corner = origin - horizontal / 2. - vertical / 2. - w;
+ let horizontal = focus_dist * viewport_width * u;
+ let vertical = focus_dist * viewport_height * v;
+ let lower_left_corner = origin - horizontal / 2. - vertical / 2. - focus_dist * w;
+
+ let lens_radius = aperture / 2.;
Self {
origin,
lower_left_corner,
horizontal,
vertical,
+ u,
+ v,
+ w,
+ lens_radius,
}
}
pub fn get_ray(&self, s: f64, t: f64) -> Ray {
- return Ray::new(
- &self.origin,
- &(self.lower_left_corner + s * &self.horizontal + t * self.vertical - self.origin),
- );
+ let rd: Vec3 = self.lens_radius * random_in_unit_disk();
+ let offset = self.u * rd.x() + self.v * rd.y();
+
+ Ray::new(
+ &(self.origin + offset),
+ &(self.lower_left_corner + s * self.horizontal + t * self.vertical
+ - self.origin
+ - offset),
+ )
}
}
@@ 90,12 90,19 @@ fn main() {
)));
// Camera
+ let lookfrom = Point3::new(3., 3., 2.);
+ let lookat = Point3::new(0., 0., -1.);
+ let vup = Vec3::new(0., 1., 0.);
+ let dist_to_focus = (lookfrom - lookat).length();
+ let aperture = 2.0;
let cam = Camera::new(
- Point3::new(-2., 2., 1.),
- Point3::new(0., 0., -1.),
- Point3::new(0., 1., 0.),
+ lookfrom,
+ lookat,
+ vup,
20.0,
aspect_ratio,
+ aperture,
+ dist_to_focus,
);
// Render
@@ 245,3 245,17 @@ pub fn refract(uv: &Vec3, n: &Vec3, etai_over_etat: f64) -> Vec3 {
let r_out_parallel = -((1.0 - r_out_perp.length_squared()).abs()).sqrt() * n;
r_out_perp + r_out_parallel
}
+
+pub fn random_in_unit_disk() -> Vec3 {
+ loop {
+ let p = Vec3::new(
+ random_double_range(-1f64..1.),
+ random_double_range(-1f64..1.),
+ 0.,
+ );
+ if p.length_squared() >= 1. {
+ continue;
+ }
+ return p;
+ }
+}