Skip to content

Commit

Permalink
implement shade testing
Browse files Browse the repository at this point in the history
  • Loading branch information
pcasaretto committed Mar 30, 2024
1 parent e56ce08 commit 5544647
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 166 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ license = "MIT"

[dependencies]
approx = "0.3.2"
impl_ops = "0.1.1"
proptest = "1.1.0"
4 changes: 2 additions & 2 deletions src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Camera {
}

pub fn pixel_size(&self) -> f64 {
return self.pixel_size;
self.pixel_size
}

pub fn ray_for_pixel(&self, x: usize, y: usize) -> Ray {
Expand Down Expand Up @@ -132,7 +132,7 @@ mod tests {
assert_eq!(ray.origin, point!(0.0, 2.0, -5.0));
assert_eq!(
ray.direction,
vector!(2.0_f64.sqrt() / 2.0, 0.0, -2.0_f64.sqrt() / 2.0)
vector!(2.0_f64.sqrt() / 2.0, 0.0, -(2.0_f64.sqrt()) / 2.0)
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ mod tests {
let red = Color::new(1.0, 0.0, 0.0);

assert_eq!(*canvas.pixel_at(0, 0), black);
canvas.write_pixel(0, 0, red.clone());
canvas.write_pixel(0, 0, red);
assert_eq!(*canvas.pixel_at(0, 0), red);
}

Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[macro_use]
extern crate impl_ops;

pub mod camera;
pub mod canvas;
pub mod color;
Expand Down
37 changes: 31 additions & 6 deletions src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ pub fn lightning(
position: Tuple,
eyev: Tuple,
normalv: Tuple,
in_shadow: bool,
) -> Color {
let effective_color = &(&material.color * &light.intensity);

let lightv = (light.position - position).norm();

let ambient = effective_color * material.ambient;

if in_shadow {
return ambient;
}

let light_dot_normal = lightv * normalv;

let mut diffuse = Color::new(0.0, 0.0, 0.0);
Expand All @@ -41,7 +46,7 @@ pub fn lightning(

let factor = reflect_dot_eye.powf(material.shininess);
specular = &light.intensity * material.specular * factor;
return ambient + diffuse + specular;
ambient + diffuse + specular
}

#[cfg(test)]
Expand All @@ -56,8 +61,8 @@ mod tests {
let position = point!(0.0, 0.0, 0.0);

let light = Light {
intensity: intensity.clone(),
position: position,
intensity,
position,
};

assert_eq!(light.intensity, intensity);
Expand All @@ -77,7 +82,7 @@ mod tests {
intensity: Color::new(1.0, 1.0, 1.0),
};

let result = lightning(&material, &light, position, eyev, normalv);
let result = lightning(&material, &light, position, eyev, normalv, false);

assert_eq!(result, Color::new(1.9, 1.9, 1.9));
}
Expand All @@ -87,16 +92,36 @@ mod tests {
let material = Material::default();
let position = point!(0.0, 0.0, 0.0);

let eyev = vector!(0.0, 2.0_f64.sqrt() / 2.0, -2.0_f64.sqrt() / 2.0);
let eyev = vector!(0.0, 2.0_f64.sqrt() / 2.0, -(2.0_f64.sqrt()) / 2.0);
let normalv = vector!(0.0, 0.0, -1.0);

let light = Light {
position: point!(0.0, 0.0, -10.0),
intensity: Color::new(1.0, 1.0, 1.0),
};

let result = lightning(&material, &light, position, eyev, normalv);
let result = lightning(&material, &light, position, eyev, normalv, false);

assert_eq!(result, Color::new(1.0, 1.0, 1.0));
}

#[test]
fn test_litghtning_with_surface_in_shadow() {
let eyev = vector!(0.0, 0.0, -1.0);
let normalv = vector!(0.0, 0.0, -1.0);
let light = Light {
position: point!(0.0, 0.0, -10.0),
intensity: Color::new(1.0, 1.0, 1.0),
};
let in_shadow = true;
let result = lightning(
&Material::default(),
&light,
point!(0.0, 0.0, 0.0),
eyev,
normalv,
in_shadow,
);
assert_eq!(result, Color::new(0.1, 0.1, 0.1));
}
}
129 changes: 28 additions & 101 deletions src/matrix.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::tuple::Tuple;
use std::ops::Mul;

#[derive(Debug)]
pub struct Matrix {
Expand Down Expand Up @@ -91,7 +90,7 @@ impl Matrix {
} else {
let first_line = &self.matrix[0];
first_line
.into_iter()
.iter()
.enumerate()
.fold(0.0, |acc, (y, item)| acc + (item * self.cofactor(0, y)))
}
Expand All @@ -106,7 +105,7 @@ impl Matrix {
let current_line = &self.matrix[x];
submatrix.push(
current_line
.into_iter()
.iter()
.enumerate()
.filter_map(
|(index, item)| if index != column { Some(*item) } else { None },
Expand Down Expand Up @@ -142,7 +141,7 @@ impl Matrix {
let current_line = &self.matrix[x];
inversed.push(
current_line
.into_iter()
.iter()
.enumerate()
.map(|(y, _item)| self.cofactor(x, y) / determinant)
.collect::<Vec<f64>>(),
Expand Down Expand Up @@ -178,7 +177,7 @@ pub fn view_transform(from: Tuple, to: Tuple, up: Tuple) -> Matrix {
-forward.x, -forward.y, -forward.z, 0.0;
0.0, 0.0, 0.0, 1.0];

return orientation * Matrix::identity(4).translation(-from.x, -from.y, -from.z);
orientation * Matrix::identity(4).translation(-from.x, -from.y, -from.z)
}

pub const EPSILON: f64 = 0.001;
Expand Down Expand Up @@ -207,112 +206,40 @@ impl PartialEq for Matrix {
}
}

impl<'a> Mul<Tuple> for &'a Matrix {
type Output = Tuple;
use std::ops;

fn mul(self, tuple: Tuple) -> Self::Output {
let matrix = matrix![tuple.x; tuple.y ; tuple.z; tuple.w ];
let result = self * &matrix;
impl_op_ex!(*|a: &Matrix, b: &Tuple| -> Tuple {
let matrix = matrix![b.x; b.y ; b.z; b.w ];
let result = a * matrix;

let x = result.matrix[0][0];
let y = result.matrix[1][0];
let z = result.matrix[2][0];
let w = result.matrix[3][0];
let x = result.matrix[0][0];
let y = result.matrix[1][0];
let z = result.matrix[2][0];
let w = result.matrix[3][0];

Tuple { x, y, z, w }
}
}

impl Mul<Tuple> for Matrix {
type Output = Tuple;

fn mul(self, tuple: Self::Output) -> Self::Output {
let matrix = matrix![tuple.x; tuple.y ; tuple.z; tuple.w ];
let result = self * &matrix;

let x = result.matrix[0][0];
let y = result.matrix[1][0];
let z = result.matrix[2][0];
let w = result.matrix[3][0];

Self::Output { x, y, z, w }
}
}

impl<'a> Mul<&Matrix> for &Matrix {
type Output = Matrix;

fn mul(self, other: &Matrix) -> Matrix {
let lines = self.matrix.len();
let columns = other.matrix[0].len();

let mut matrix = vec![vec![0.0; columns]; lines];

for x in 0..lines {
for y in 0..columns {
let mut sum = 0.0;
for pos in 0..lines {
let item = self.matrix[x][pos];
let item_b = other.matrix[pos][y];
sum += item * item_b;
}
matrix[x][y] = sum
}
}

Matrix { matrix }
}
}
Tuple { x, y, z, w }
});

impl Mul<&Matrix> for Matrix {
type Output = Self;
impl_op_ex!(*|a: &Matrix, b: &Matrix| -> Matrix {
let lines = a.matrix.len();
let columns = b.matrix[0].len();

fn mul(self, other: &Matrix) -> Self {
let lines = self.matrix.len();
let columns = other.matrix[0].len();

let mut matrix = vec![vec![0.0; columns]; lines];
let mut matrix = vec![vec![0.0; columns]; lines];

for x in 0..lines {
for y in 0..columns {
let mut sum = 0.0;
for pos in 0..lines {
let item = self.matrix[x][pos];
let item_b = other.matrix[pos][y];
sum += item * item_b;
}
matrix[x][y] = sum
for x in 0..lines {
for y in 0..columns {
let mut sum = 0.0;
for pos in 0..lines {
let item = a.matrix[x][pos];
let item_b = b.matrix[pos][y];
sum += item * item_b;
}
matrix[x][y] = sum
}

Self { matrix }
}
}

impl Mul for Matrix {
type Output = Self;

fn mul(self, other: Self) -> Self {
let lines = self.matrix.len();
let columns = other.matrix[0].len();

let mut matrix = vec![vec![0.0; columns]; lines];

for x in 0..lines {
for y in 0..columns {
let mut sum = 0.0;
for pos in 0..lines {
let item = self.matrix[x][pos];
let item_b = other.matrix[pos][y];
sum += item * item_b;
}
matrix[x][y] = sum
}
}

Self { matrix }
}
}
Matrix { matrix }
});

#[cfg(test)]
mod tests {
Expand Down
8 changes: 4 additions & 4 deletions src/ray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Intersection<'_> {
}
Computation {
t: self.t,
object: &self.object,
object: self.object,
point,
eyev,
normalv,
Expand Down Expand Up @@ -393,7 +393,7 @@ mod tests {
assert_eq!(comps.point, point!(0.0, 0.0, -1.0));
assert_eq!(comps.eyev, vector!(0.0, 0.0, -1.0));
assert_eq!(comps.normalv, vector!(0.0, 0.0, -1.0));
assert_eq!(comps.inside, false);
assert!(!comps.inside);
}

// test intersection precomputation calculations when intersection occurs on the inside of the sphere
Expand All @@ -415,7 +415,7 @@ mod tests {
assert_eq!(comps.point, point!(0.0, 0.0, 1.0));
assert_eq!(comps.eyev, vector!(0.0, 0.0, -1.0));
assert_eq!(comps.normalv, vector!(0.0, 0.0, -1.0));
assert_eq!(comps.inside, true);
assert!(comps.inside);
}

// test shading an intersection
Expand Down Expand Up @@ -534,7 +534,7 @@ mod tests {
.rotation_z(PI / 5.0)
.scaling(1.0, 0.5, 1.0);

let n = sphere.normal_at(point!(0.0, 2.0_f64.sqrt() / 2.0, -2.0_f64.sqrt() / 2.0));
let n = sphere.normal_at(point!(0.0, 2.0_f64.sqrt() / 2.0, -(2.0_f64.sqrt()) / 2.0));

assert_eq!(n, vector!(0.0, 0.97014, -0.24254));
}
Expand Down
Loading

0 comments on commit 5544647

Please sign in to comment.