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.
This commit is contained in:
Bruno BELANYI 2020-03-29 19:24:25 +02:00
parent 2f3224ea07
commit 9ad1100ded

View file

@ -12,6 +12,8 @@ use serde::Deserialize;
pub struct Camera { pub struct Camera {
/// Where the camera is set in the scene (i.e: its focal point). /// Where the camera is set in the scene (i.e: its focal point).
origin: 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. /// The film to represent each pixel in the scene.
film: Film, film: Film,
} }
@ -40,15 +42,20 @@ impl Camera {
forward: Vector, forward: Vector,
up: Vector, up: Vector,
fov: f32, fov: f32,
dist_to_image: f32, distance_to_image: f32,
x: u32, x: u32,
y: u32, y: u32,
) -> Self { ) -> Self {
let right = forward.cross(&up); let right = forward.cross(&up);
let center = origin + forward.normalize() * dist_to_image; let screen_size = 2. * f32::tan(fov / 2.);
let screen_size = 2. * f32::tan(fov / 2.) * dist_to_image; // Construct the film behind the camera, upside down
let film = Film::new(x, y, screen_size, center, up, right); let center = origin - forward.normalize();
Camera { origin, film } let film = Film::new(x, y, screen_size, center, -up, -right);
Camera {
origin,
distance_to_image,
film,
}
} }
/// Get the `Camera`'s [`Film`]. /// Get the `Camera`'s [`Film`].
@ -96,7 +103,7 @@ impl Camera {
/// ``` /// ```
pub fn ray_with_ratio(&self, x: f32, y: f32) -> Ray { pub fn ray_with_ratio(&self, x: f32, y: f32) -> Ray {
let pixel = self.film().pixel_at_ratio(x, y); 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) Ray::new(pixel, direction)
} }
} }
@ -168,7 +175,7 @@ mod test {
#[test] #[test]
fn new_works() { fn new_works() {
let cam = Camera::new( let cam = Camera::new(
Point::new(-1., 0., 0.), Point::new(1., 0., 0.),
Vector::new(1., 0., 0.), Vector::new(1., 0., 0.),
Vector::new(0., 1., 0.), Vector::new(0., 1., 0.),
2. * f32::atan(1.), /* 90° in radian */ 2. * f32::atan(1.), /* 90° in radian */
@ -179,14 +186,15 @@ mod test {
assert_eq!( assert_eq!(
cam, cam,
Camera { Camera {
origin: Point::new(-1., 0., 0.), origin: Point::new(1., 0., 0.),
distance_to_image: 1.,
film: Film::new( film: Film::new(
1080, 1080,
1080, 1080,
2., 2.,
Point::origin(), Point::origin(),
Vector::new(0., 1., 0.), -Vector::new(0., 1., 0.),
Vector::new(0., 0., 1.), -Vector::new(0., 0., 1.),
) )
} }
) )
@ -195,7 +203,7 @@ mod test {
#[test] #[test]
fn deserialization_works() { fn deserialization_works() {
let yaml = r#" let yaml = r#"
origin: [-1.0, 0.0, 0.0] origin: [1.0, 0.0, 0.0]
forward: [ 1.0, 0.0, 0.0] forward: [ 1.0, 0.0, 0.0]
up: [0.0, 1.0, 0.0] up: [0.0, 1.0, 0.0]
fov: 90.0 fov: 90.0
@ -207,14 +215,15 @@ mod test {
assert_eq!( assert_eq!(
cam, cam,
Camera { Camera {
origin: Point::new(-1., 0., 0.), origin: Point::new(1., 0., 0.),
distance_to_image: 1.0,
film: Film::new( film: Film::new(
1080, 1080,
1080, 1080,
2., 2.,
Point::origin(), Point::origin(),
Vector::new(0., 1., 0.), -Vector::new(0., 1., 0.),
Vector::new(0., 0., 1.), -Vector::new(0., 0., 1.),
) )
} }
) )