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_position = Tuple::point(-10., 10., -10.);
|
||||||
let light_color = WHITE;
|
let light_color = WHITE;
|
||||||
let light = PointLight::new(light_position, light_color);
|
let light = PointLight::new(light_position, light_color);
|
||||||
|
let in_shadow = false;
|
||||||
for y in 0..h {
|
for y in 0..h {
|
||||||
let world_y = half - pixel_size * y as f32;
|
let world_y = half - pixel_size * y as f32;
|
||||||
for x in 0..w {
|
for x in 0..w {
|
||||||
@ -44,7 +44,7 @@ fn main() -> Result<()> {
|
|||||||
let point = r.position(hit.t);
|
let point = r.position(hit.t);
|
||||||
let normal = hit.object.normal_at(point);
|
let normal = hit.object.normal_at(point);
|
||||||
let eye = -r.direction;
|
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);
|
c.set(x, y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,7 @@ impl Default for Material {
|
|||||||
/// WHITE,
|
/// WHITE,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
|
/// let in_shadow = false;
|
||||||
/// let m = Material::default();
|
/// let m = Material::default();
|
||||||
/// let position = Tuple::point(0., 0., 0.);
|
/// let position = Tuple::point(0., 0., 0.);
|
||||||
///
|
///
|
||||||
@ -61,35 +62,43 @@ impl Default for Material {
|
|||||||
/// let eyev = Tuple::vector(0., 0., -1.);
|
/// let eyev = Tuple::vector(0., 0., -1.);
|
||||||
/// let normalv = Tuple::vector(0., 0., -1.);
|
/// let normalv = Tuple::vector(0., 0., -1.);
|
||||||
/// let light = PointLight::new(Tuple::point(0., 0., -10.), WHITE);
|
/// 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));
|
/// assert_eq!(result, Color::new(1.9, 1.9, 1.9));
|
||||||
///
|
///
|
||||||
/// // Lighting with the eye between the light and the surface, eye offset 45°.
|
/// // 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 eyev = Tuple::vector(0., 2_f32.sqrt() / 2., -2_f32.sqrt() / 2.);
|
||||||
/// let normalv = Tuple::vector(0., 0., -1.);
|
/// let normalv = Tuple::vector(0., 0., -1.);
|
||||||
/// let light = PointLight::new(Tuple::point(0., 0., -10.), WHITE);
|
/// 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);
|
/// assert_eq!(result, WHITE);
|
||||||
///
|
///
|
||||||
/// // Lighting with the eye opposite surface, light offset 45°.
|
/// // Lighting with the eye opposite surface, light offset 45°.
|
||||||
/// let eyev = Tuple::vector(0., 0., -1.);
|
/// let eyev = Tuple::vector(0., 0., -1.);
|
||||||
/// let normalv = Tuple::vector(0., 0., -1.);
|
/// let normalv = Tuple::vector(0., 0., -1.);
|
||||||
/// let light = PointLight::new(Tuple::point(0., 10., -10.), WHITE);
|
/// 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));
|
/// assert_eq!(result, Color::new(0.7364, 0.7364, 0.7364));
|
||||||
///
|
///
|
||||||
/// // Lighting with the eye in the path of the reflection vector.
|
/// // 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 eyev = Tuple::vector(0., -2_f32.sqrt() / 2., -2_f32.sqrt() / 2.);
|
||||||
/// let normalv = Tuple::vector(0., 0., -1.);
|
/// let normalv = Tuple::vector(0., 0., -1.);
|
||||||
/// let light = PointLight::new(Tuple::point(0., 10., -10.), WHITE);
|
/// 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));
|
/// assert_eq!(result, Color::new(1.6363853, 1.6363853, 1.6363853));
|
||||||
///
|
///
|
||||||
/// // Lighting with the light behind the surface.
|
/// // Lighting with the light behind the surface.
|
||||||
/// let eyev = Tuple::vector(0., 0., -1.);
|
/// let eyev = Tuple::vector(0., 0., -1.);
|
||||||
/// let normalv = Tuple::vector(0., 0., -1.);
|
/// let normalv = Tuple::vector(0., 0., -1.);
|
||||||
/// let light = PointLight::new(Tuple::point(0., 0., 10.), WHITE);
|
/// 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));
|
/// assert_eq!(result, Color::new(0.1, 0.1, 0.1));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn lighting(
|
pub fn lighting(
|
||||||
@ -98,6 +107,7 @@ pub fn lighting(
|
|||||||
point: Tuple,
|
point: Tuple,
|
||||||
eyev: Tuple,
|
eyev: Tuple,
|
||||||
normalv: Tuple,
|
normalv: Tuple,
|
||||||
|
in_shadow: bool,
|
||||||
) -> Color {
|
) -> Color {
|
||||||
// Combine the surface color with the light's color.
|
// Combine the surface color with the light's color.
|
||||||
let effective_color = material.color * light.intensity;
|
let effective_color = material.color * light.intensity;
|
||||||
@ -128,5 +138,9 @@ pub fn lighting(
|
|||||||
};
|
};
|
||||||
(diffuse, specular)
|
(diffuse, specular)
|
||||||
};
|
};
|
||||||
|
if in_shadow {
|
||||||
|
ambient
|
||||||
|
} else {
|
||||||
ambient + diffuse + specular
|
ambient + diffuse + specular
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -119,12 +119,14 @@ impl World {
|
|||||||
pub fn shade_hit(&self, comps: &PrecomputedData) -> Color {
|
pub fn shade_hit(&self, comps: &PrecomputedData) -> Color {
|
||||||
// TODO(wathiede): support multiple light sources by iterating over all
|
// TODO(wathiede): support multiple light sources by iterating over all
|
||||||
// the light sources and summing the calls to lighting.
|
// the light sources and summing the calls to lighting.
|
||||||
|
let in_shadow = false;
|
||||||
lighting(
|
lighting(
|
||||||
&comps.object.material,
|
&comps.object.material,
|
||||||
&self.light.as_ref().expect("World has no lights"),
|
&self.light.as_ref().expect("World has no lights"),
|
||||||
comps.point,
|
comps.point,
|
||||||
comps.eyev,
|
comps.eyev,
|
||||||
comps.normalv,
|
comps.normalv,
|
||||||
|
in_shadow,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/// Compute color for given ray fired at the world.
|
/// Compute color for given ray fired at the world.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user