materials: make lighting calculation shadow aware
This commit is contained in:
parent
efdc963a48
commit
1065702a5d
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user