camera & spheres: add feature tag disable_inverse_cache
This commit is contained in:
parent
538b8ad364
commit
2eeeb2013b
@ -6,6 +6,9 @@ edition = "2018"
|
|||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
disable_inverse_cache = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.41"
|
anyhow = "1.0.41"
|
||||||
criterion = "0.3.4"
|
criterion = "0.3.4"
|
||||||
|
|||||||
@ -112,6 +112,7 @@ impl Camera {
|
|||||||
/// Tuple::vector(2_f32.sqrt() / 2., 0., -2_f32.sqrt() / 2.)
|
/// Tuple::vector(2_f32.sqrt() / 2., 0., -2_f32.sqrt() / 2.)
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(not(feature = "disable_inverse_cache"))]
|
||||||
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
|
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
|
||||||
// The offset from the edge of the canvas to the pixel's corner.
|
// The offset from the edge of the canvas to the pixel's corner.
|
||||||
let xoffset = (px as f32 + 0.5) * self.pixel_size;
|
let xoffset = (px as f32 + 0.5) * self.pixel_size;
|
||||||
@ -124,16 +125,35 @@ impl Camera {
|
|||||||
|
|
||||||
// Using the camera matrix, transofmrm the canvas point and the origin,
|
// Using the camera matrix, transofmrm the canvas point and the origin,
|
||||||
// and then compute the ray's direction vector.
|
// and then compute the ray's direction vector.
|
||||||
// (Remember that the canves is at z>=-1).
|
// (Remember that the canvas is at z>=-1).
|
||||||
let pixel = self.inverse_transform * Tuple::point(world_x, world_y, -1.);
|
let pixel = self.inverse_transform * Tuple::point(world_x, world_y, -1.);
|
||||||
let origin = self.inverse_transform * Tuple::point(0., 0., 0.);
|
let origin = self.inverse_transform * Tuple::point(0., 0., 0.);
|
||||||
let direction = (pixel - origin).normalize();
|
let direction = (pixel - origin).normalize();
|
||||||
|
|
||||||
Ray::new(origin, direction)
|
Ray::new(origin, direction)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "disable_inverse_cache")]
|
||||||
|
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
|
||||||
|
// The offset from the edge of the canvas to the pixel's corner.
|
||||||
|
let xoffset = (px as f32 + 0.5) * self.pixel_size;
|
||||||
|
let yoffset = (py as f32 + 0.5) * self.pixel_size;
|
||||||
|
|
||||||
|
// The untransformed coordinates of the pixle in world space.
|
||||||
|
// (Remember that the camera looks toward -z, so +x is to the left.)
|
||||||
|
let world_x = self.half_width - xoffset;
|
||||||
|
let world_y = self.half_height - yoffset;
|
||||||
|
|
||||||
|
// Using the camera matrix, transofmrm the canvas point and the origin,
|
||||||
|
// and then compute the ray's direction vector.
|
||||||
|
// (Remember that the canvas is at z>=-1).
|
||||||
|
let pixel = self.transform.inverse() * Tuple::point(world_x, world_y, -1.);
|
||||||
|
let origin = self.transform.inverse() * Tuple::point(0., 0., 0.);
|
||||||
|
let direction = (pixel - origin).normalize();
|
||||||
|
|
||||||
|
Ray::new(origin, direction)
|
||||||
|
}
|
||||||
|
|
||||||
/// Use camera to render an image of the given world.
|
/// Use camera to render an image of the given world.
|
||||||
///
|
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::f32::consts::PI;
|
/// use std::f32::consts::PI;
|
||||||
@ -160,7 +180,28 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn render_parallel(&self, w: &World) -> Canvas {
|
fn render_parallel_one_tread_per_core(&self, w: &World) -> Canvas {
|
||||||
|
let image_mu = Mutex::new(Canvas::new(self.hsize, self.vsize, BLACK));
|
||||||
|
|
||||||
|
(0..self.vsize).into_par_iter().for_each(|y| {
|
||||||
|
let mut row_image = Canvas::new(self.hsize, 1, BLACK);
|
||||||
|
for x in 0..self.hsize {
|
||||||
|
let ray = self.ray_for_pixel(x, y);
|
||||||
|
let color = w.color_at(&ray);
|
||||||
|
row_image.set(x, 0, color);
|
||||||
|
}
|
||||||
|
// TODO(wathiede): create a row based setter for memcpying the row as a whole.
|
||||||
|
let mut image = image_mu.lock().expect("failed to lock image mutex");
|
||||||
|
for x in 0..self.hsize {
|
||||||
|
image.set(x, y, row_image.get(x, 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
image_mu
|
||||||
|
.into_inner()
|
||||||
|
.expect("failed to get image out of mutex")
|
||||||
|
}
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn render_parallel_rayon(&self, w: &World) -> Canvas {
|
||||||
let image_mu = Mutex::new(Canvas::new(self.hsize, self.vsize, BLACK));
|
let image_mu = Mutex::new(Canvas::new(self.hsize, self.vsize, BLACK));
|
||||||
|
|
||||||
(0..self.vsize).into_par_iter().for_each(|y| {
|
(0..self.vsize).into_par_iter().for_each(|y| {
|
||||||
|
|||||||
@ -105,6 +105,7 @@ impl Sphere {
|
|||||||
/// let n = s.normal_at(Tuple::point(0., 2_f32.sqrt()/2., -2_f32.sqrt()/2.));
|
/// let n = s.normal_at(Tuple::point(0., 2_f32.sqrt()/2., -2_f32.sqrt()/2.));
|
||||||
/// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254));
|
/// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254));
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(not(feature = "disable_inverse_cache"))]
|
||||||
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
||||||
let object_point = self.inverse_transform * world_point;
|
let object_point = self.inverse_transform * world_point;
|
||||||
let object_normal = object_point - Tuple::point(0., 0., 0.);
|
let object_normal = object_point - Tuple::point(0., 0., 0.);
|
||||||
@ -112,6 +113,14 @@ impl Sphere {
|
|||||||
world_normal.w = 0.;
|
world_normal.w = 0.;
|
||||||
world_normal.normalize()
|
world_normal.normalize()
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "disable_inverse_cache")]
|
||||||
|
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
||||||
|
let object_point = self.transform.inverse() * world_point;
|
||||||
|
let object_normal = object_point - Tuple::point(0., 0., 0.);
|
||||||
|
let mut world_normal = self.transform.inverse().transpose() * object_normal;
|
||||||
|
world_normal.w = 0.;
|
||||||
|
world_normal.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn transform(&self) -> Matrix4x4 {
|
pub fn transform(&self) -> Matrix4x4 {
|
||||||
self.transform
|
self.transform
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user