From 9ad1100dedba2d29fef013fda8891f501be8c0e2 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Sun, 29 Mar 2020 19:24:25 +0200 Subject: [PATCH] library: core: camera: move film behind the camera To prepare for adding the handling of focal blur, move the film so that it is behind the point of convergence of the lens. In addition, store the distance to the focal plane in the camera, which will be used when calculating rays with an non-zero aperture. --- pathtracer/src/core/camera.rs | 37 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/pathtracer/src/core/camera.rs b/pathtracer/src/core/camera.rs index 7564101..8bc7f51 100644 --- a/pathtracer/src/core/camera.rs +++ b/pathtracer/src/core/camera.rs @@ -12,6 +12,8 @@ use serde::Deserialize; pub struct Camera { /// Where the camera is set in the scene (i.e: its focal point). origin: Point, + /// How far away is the camera's plan of focus. + distance_to_image: f32, /// The film to represent each pixel in the scene. film: Film, } @@ -40,15 +42,20 @@ impl Camera { forward: Vector, up: Vector, fov: f32, - dist_to_image: f32, + distance_to_image: f32, x: u32, y: u32, ) -> Self { let right = forward.cross(&up); - let center = origin + forward.normalize() * dist_to_image; - let screen_size = 2. * f32::tan(fov / 2.) * dist_to_image; - let film = Film::new(x, y, screen_size, center, up, right); - Camera { origin, film } + let screen_size = 2. * f32::tan(fov / 2.); + // Construct the film behind the camera, upside down + let center = origin - forward.normalize(); + let film = Film::new(x, y, screen_size, center, -up, -right); + Camera { + origin, + distance_to_image, + film, + } } /// Get the `Camera`'s [`Film`]. @@ -96,7 +103,7 @@ impl Camera { /// ``` pub fn ray_with_ratio(&self, x: f32, y: f32) -> Ray { let pixel = self.film().pixel_at_ratio(x, y); - let direction = Unit::new_normalize(pixel - self.origin()); + let direction = Unit::new_normalize(self.origin() - pixel); Ray::new(pixel, direction) } } @@ -168,7 +175,7 @@ mod test { #[test] fn new_works() { let cam = Camera::new( - Point::new(-1., 0., 0.), + Point::new(1., 0., 0.), Vector::new(1., 0., 0.), Vector::new(0., 1., 0.), 2. * f32::atan(1.), /* 90° in radian */ @@ -179,14 +186,15 @@ mod test { assert_eq!( cam, Camera { - origin: Point::new(-1., 0., 0.), + origin: Point::new(1., 0., 0.), + distance_to_image: 1., film: Film::new( 1080, 1080, 2., Point::origin(), - Vector::new(0., 1., 0.), - Vector::new(0., 0., 1.), + -Vector::new(0., 1., 0.), + -Vector::new(0., 0., 1.), ) } ) @@ -195,7 +203,7 @@ mod test { #[test] fn deserialization_works() { let yaml = r#" - origin: [-1.0, 0.0, 0.0] + origin: [1.0, 0.0, 0.0] forward: [ 1.0, 0.0, 0.0] up: [0.0, 1.0, 0.0] fov: 90.0 @@ -207,14 +215,15 @@ mod test { assert_eq!( cam, Camera { - origin: Point::new(-1., 0., 0.), + origin: Point::new(1., 0., 0.), + distance_to_image: 1.0, film: Film::new( 1080, 1080, 2., Point::origin(), - Vector::new(0., 1., 0.), - Vector::new(0., 0., 1.), + -Vector::new(0., 1., 0.), + -Vector::new(0., 0., 1.), ) } )