world: implement World::color_at
This commit is contained in:
parent
86d052d38b
commit
b37398ac40
@ -1,11 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
intersections::{Intersections, PrecomputedData},
|
intersections::{prepare_computations, Intersections, PrecomputedData},
|
||||||
lights::PointLight,
|
lights::PointLight,
|
||||||
materials::{lighting, Material},
|
materials::{lighting, Material},
|
||||||
matrices::Matrix4x4,
|
matrices::Matrix4x4,
|
||||||
rays::Ray,
|
rays::Ray,
|
||||||
spheres::{intersect, Sphere},
|
spheres::{intersect, Sphere},
|
||||||
tuples::{Color, Tuple},
|
tuples::{Color, Tuple},
|
||||||
|
BLACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// World holds all drawable objects and the light(s) that illuminate them.
|
/// World holds all drawable objects and the light(s) that illuminate them.
|
||||||
@ -118,6 +119,8 @@ impl World {
|
|||||||
/// assert_eq!(c, Color::new(0.90498, 0.90498, 0.90498));
|
/// assert_eq!(c, Color::new(0.90498, 0.90498, 0.90498));
|
||||||
/// ```
|
/// ```
|
||||||
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
|
||||||
|
// the light sources and summing the calls to lighting.
|
||||||
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"),
|
||||||
@ -126,4 +129,51 @@ impl World {
|
|||||||
comps.normalv,
|
comps.normalv,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
/// Compute color for given ray fired at the world.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use rtchallenge::{
|
||||||
|
/// intersections::{prepare_computations, Intersection},
|
||||||
|
/// lights::PointLight,
|
||||||
|
/// rays::Ray,
|
||||||
|
/// tuples::{Color, Tuple},
|
||||||
|
/// world::World,
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // The color when a ray misses.
|
||||||
|
/// let w = World::test_world();
|
||||||
|
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 1., 0.));
|
||||||
|
/// let c = w.color_at(&r);
|
||||||
|
/// assert_eq!(c, Color::new(0., 0., 0.));
|
||||||
|
///
|
||||||
|
/// // The color when a ray hits.
|
||||||
|
/// let w = World::test_world();
|
||||||
|
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.));
|
||||||
|
/// let c = w.color_at(&r);
|
||||||
|
/// assert_eq!(c, Color::new(0.38066, 0.47583, 0.2855));
|
||||||
|
///
|
||||||
|
/// // The color with an intersection behind the ray.
|
||||||
|
/// let w = {
|
||||||
|
/// let mut w = World::test_world();
|
||||||
|
/// let mut outer = &mut w.objects[0];
|
||||||
|
/// outer.material.ambient = 1.;
|
||||||
|
/// let inner = &mut w.objects[1];
|
||||||
|
/// inner.material.ambient = 1.;
|
||||||
|
/// w
|
||||||
|
/// };
|
||||||
|
/// let inner = &w.objects[1];
|
||||||
|
/// let r = Ray::new(Tuple::point(0., 0., 0.75), Tuple::vector(0., 0., -1.));
|
||||||
|
/// let c = w.color_at(&r);
|
||||||
|
/// assert_eq!(c, inner.material.color);
|
||||||
|
/// ```
|
||||||
|
pub fn color_at(&self, r: &Ray) -> Color {
|
||||||
|
match self.intersect(r).hit() {
|
||||||
|
Some(hit) => {
|
||||||
|
let comps = prepare_computations(&hit, r);
|
||||||
|
self.shade_hit(&comps)
|
||||||
|
}
|
||||||
|
None => BLACK,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user