From 1065702a5d80123f4a64b70ca01a74f522c57b7a Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sun, 18 Jul 2021 12:46:49 -0700 Subject: [PATCH] materials: make lighting calculation shadow aware --- rtchallenge/examples/eoc6.rs | 4 ++-- rtchallenge/src/materials.rs | 26 ++++++++++++++++++++------ rtchallenge/src/world.rs | 2 ++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/rtchallenge/examples/eoc6.rs b/rtchallenge/examples/eoc6.rs index 28043a8..959c22f 100644 --- a/rtchallenge/examples/eoc6.rs +++ b/rtchallenge/examples/eoc6.rs @@ -31,7 +31,7 @@ fn main() -> Result<()> { let light_position = Tuple::point(-10., 10., -10.); let light_color = WHITE; let light = PointLight::new(light_position, light_color); - + let in_shadow = false; for y in 0..h { let world_y = half - pixel_size * y as f32; for x in 0..w { @@ -44,7 +44,7 @@ fn main() -> Result<()> { let point = r.position(hit.t); let normal = hit.object.normal_at(point); let eye = -r.direction; - let color = lighting(&hit.object.material, &light, point, eye, normal); + let color = lighting(&hit.object.material, &light, point, eye, normal, in_shadow); c.set(x, y, color); } } diff --git a/rtchallenge/src/materials.rs b/rtchallenge/src/materials.rs index 9b76a33..671bf08 100644 --- a/rtchallenge/src/materials.rs +++ b/rtchallenge/src/materials.rs @@ -54,6 +54,7 @@ impl Default for Material { /// WHITE, /// }; /// +/// let in_shadow = false; /// let m = Material::default(); /// let position = Tuple::point(0., 0., 0.); /// @@ -61,35 +62,43 @@ impl Default for Material { /// let eyev = Tuple::vector(0., 0., -1.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 0., -10.), WHITE); -/// let result = lighting(&m, &light, position, eyev, normalv); +/// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); /// assert_eq!(result, Color::new(1.9, 1.9, 1.9)); /// /// // Lighting with the eye between the light and the surface, eye offset 45°. /// let eyev = Tuple::vector(0., 2_f32.sqrt() / 2., -2_f32.sqrt() / 2.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 0., -10.), WHITE); -/// let result = lighting(&m, &light, position, eyev, normalv); +/// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); /// assert_eq!(result, WHITE); /// /// // Lighting with the eye opposite surface, light offset 45°. /// let eyev = Tuple::vector(0., 0., -1.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 10., -10.), WHITE); -/// let result = lighting(&m, &light, position, eyev, normalv); +/// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); /// assert_eq!(result, Color::new(0.7364, 0.7364, 0.7364)); /// /// // Lighting with the eye in the path of the reflection vector. /// let eyev = Tuple::vector(0., -2_f32.sqrt() / 2., -2_f32.sqrt() / 2.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 10., -10.), WHITE); -/// let result = lighting(&m, &light, position, eyev, normalv); +/// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); /// assert_eq!(result, Color::new(1.6363853, 1.6363853, 1.6363853)); /// /// // Lighting with the light behind the surface. /// let eyev = Tuple::vector(0., 0., -1.); /// let normalv = Tuple::vector(0., 0., -1.); /// let light = PointLight::new(Tuple::point(0., 0., 10.), WHITE); -/// let result = lighting(&m, &light, position, eyev, normalv); +/// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); +/// assert_eq!(result, Color::new(0.1, 0.1, 0.1)); +/// +/// // Lighting with the surface in shadow. +/// let in_shadow = true; +/// let eyev = Tuple::vector(0., 0., -1.); +/// let normalv = Tuple::vector(0., 0., -1.); +/// let light = PointLight::new(Tuple::point(0., 0., -10.), WHITE); +/// let result = lighting(&m, &light, position, eyev, normalv, in_shadow); /// assert_eq!(result, Color::new(0.1, 0.1, 0.1)); /// ``` pub fn lighting( @@ -98,6 +107,7 @@ pub fn lighting( point: Tuple, eyev: Tuple, normalv: Tuple, + in_shadow: bool, ) -> Color { // Combine the surface color with the light's color. let effective_color = material.color * light.intensity; @@ -128,5 +138,9 @@ pub fn lighting( }; (diffuse, specular) }; - ambient + diffuse + specular + if in_shadow { + ambient + } else { + ambient + diffuse + specular + } } diff --git a/rtchallenge/src/world.rs b/rtchallenge/src/world.rs index 13a875e..121e737 100644 --- a/rtchallenge/src/world.rs +++ b/rtchallenge/src/world.rs @@ -119,12 +119,14 @@ impl World { pub fn shade_hit(&self, comps: &PrecomputedData) -> Color { // TODO(wathiede): support multiple light sources by iterating over all // the light sources and summing the calls to lighting. + let in_shadow = false; lighting( &comps.object.material, &self.light.as_ref().expect("World has no lights"), comps.point, comps.eyev, comps.normalv, + in_shadow, ) } /// Compute color for given ray fired at the world.