materials: move tests from doctest to unit.
This commit is contained in:
parent
f476822bcd
commit
1d5e5a164b
@ -24,26 +24,6 @@ pub struct Material {
|
||||
|
||||
impl Default for Material {
|
||||
/// Creates the default material.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{materials::Material, tuples::Color, WHITE};
|
||||
///
|
||||
/// let m = Material::default();
|
||||
/// assert_eq!(
|
||||
/// m,
|
||||
/// Material {
|
||||
/// color: WHITE.into(),
|
||||
/// ambient: 0.1,
|
||||
/// diffuse: 0.9,
|
||||
/// specular: 0.9,
|
||||
/// shininess: 200.,
|
||||
/// reflective: 0.0,
|
||||
/// transparency: 0.0,
|
||||
/// refractive_index: 1.0,
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
fn default() -> Material {
|
||||
Material {
|
||||
color: WHITE.into(),
|
||||
@ -59,99 +39,6 @@ impl Default for Material {
|
||||
}
|
||||
|
||||
/// Compute lighting contributions using the Phong reflection model.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// lights::PointLight,
|
||||
/// materials::{lighting, Material},
|
||||
/// patterns::Pattern,
|
||||
/// shapes::Shape,
|
||||
/// tuples::{point, vector, Color},
|
||||
/// Float, BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// let in_shadow = false;
|
||||
/// let m = Material::default();
|
||||
/// let position = point(0., 0., 0.);
|
||||
/// let object = Shape::sphere();
|
||||
///
|
||||
/// // Lighting with the eye between the light and the surface.
|
||||
/// let eyev = vector(0., 0., -1.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
/// let result = lighting(&m, &object, &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 = vector(0., (2. as Float).sqrt() / 2., -(2. as Float).sqrt() / 2.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
/// let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
/// assert_eq!(result, WHITE);
|
||||
///
|
||||
/// // Lighting with the eye opposite surface, light offset 45°.
|
||||
/// let eyev = vector(0., 0., -1.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 10., -10.), WHITE);
|
||||
/// let result = lighting(&m, &object, &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 = vector(0., -(2.0 as Float).sqrt() / 2., -(2.0 as Float).sqrt() / 2.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 10., -10.), WHITE);
|
||||
/// let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
/// assert_eq!(result, Color::new(1.63639, 1.63639, 1.63639));
|
||||
///
|
||||
/// // Lighting with the light behind the surface.
|
||||
/// let eyev = vector(0., 0., -1.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 0., 10.), WHITE);
|
||||
/// let result = lighting(&m, &object, &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 = vector(0., 0., -1.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
/// let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
/// assert_eq!(result, Color::new(0.1, 0.1, 0.1));
|
||||
///
|
||||
/// // Lighting with a pattern applied.
|
||||
///
|
||||
/// let m = Material {
|
||||
/// color: Pattern::stripe(WHITE, BLACK),
|
||||
/// ambient: 1.,
|
||||
/// diffuse: 0.,
|
||||
/// specular: 0.,
|
||||
/// ..Material::default()
|
||||
/// };
|
||||
/// let eyev = vector(0., 0., -1.);
|
||||
/// let normalv = vector(0., 0., -1.);
|
||||
/// let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
/// let c1 = lighting(
|
||||
/// &m,
|
||||
/// &object,
|
||||
/// &light,
|
||||
/// point(0.9, 0., 0.),
|
||||
/// eyev,
|
||||
/// normalv,
|
||||
/// false,
|
||||
/// );
|
||||
/// let c2 = lighting(
|
||||
/// &m,
|
||||
/// &object,
|
||||
/// &light,
|
||||
/// point(1.1, 0., 0.),
|
||||
/// eyev,
|
||||
/// normalv,
|
||||
/// false,
|
||||
/// );
|
||||
/// assert_eq!(c1, WHITE);
|
||||
/// assert_eq!(c2, BLACK);
|
||||
/// ```
|
||||
pub fn lighting(
|
||||
material: &Material,
|
||||
object: &Shape,
|
||||
@ -197,3 +84,153 @@ pub fn lighting(
|
||||
ambient + diffuse + specular
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{materials::Material, WHITE};
|
||||
|
||||
#[test]
|
||||
fn default() {
|
||||
let m = Material::default();
|
||||
assert_eq!(
|
||||
m,
|
||||
Material {
|
||||
color: WHITE.into(),
|
||||
ambient: 0.1,
|
||||
diffuse: 0.9,
|
||||
specular: 0.9,
|
||||
shininess: 200.,
|
||||
reflective: 0.0,
|
||||
transparency: 0.0,
|
||||
refractive_index: 1.0,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
mod lighting {
|
||||
use crate::{
|
||||
lights::PointLight,
|
||||
materials::{lighting, Material},
|
||||
patterns::Pattern,
|
||||
shapes::Shape,
|
||||
tuples::{point, vector, Color},
|
||||
Float, BLACK, WHITE,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn eye_between_light_and_surface() {
|
||||
let in_shadow = false;
|
||||
let m = Material::default();
|
||||
let position = point(0., 0., 0.);
|
||||
let object = Shape::sphere();
|
||||
|
||||
// Lighting with the eye between the light and the surface.
|
||||
let eyev = vector(0., 0., -1.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
assert_eq!(result, Color::new(1.9, 1.9, 1.9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eye_between_light_and_surface_offset_45() {
|
||||
// Lighting with the eye between the light and the surface, eye offset 45°.
|
||||
let in_shadow = false;
|
||||
let m = Material::default();
|
||||
let position = point(0., 0., 0.);
|
||||
let object = Shape::sphere();
|
||||
let eyev = vector(0., (2. as Float).sqrt() / 2., -(2. as Float).sqrt() / 2.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
assert_eq!(result, WHITE);
|
||||
}
|
||||
#[test]
|
||||
fn eye_opposite_surface_light_offset_45() {
|
||||
// Lighting with the eye opposite surface, light offset 45°.
|
||||
let in_shadow = false;
|
||||
let m = Material::default();
|
||||
let position = point(0., 0., 0.);
|
||||
let object = Shape::sphere();
|
||||
let eyev = vector(0., 0., -1.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 10., -10.), WHITE);
|
||||
let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
assert_eq!(result, Color::new(0.7364, 0.7364, 0.7364));
|
||||
}
|
||||
#[test]
|
||||
fn eye_in_path_of_reflection_vector() {
|
||||
// Lighting with the eye in the path of the reflection vector.
|
||||
let in_shadow = false;
|
||||
let m = Material::default();
|
||||
let position = point(0., 0., 0.);
|
||||
let object = Shape::sphere();
|
||||
let eyev = vector(0., -(2.0 as Float).sqrt() / 2., -(2.0 as Float).sqrt() / 2.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 10., -10.), WHITE);
|
||||
let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
assert_eq!(result, Color::new(1.63639, 1.63639, 1.63639));
|
||||
}
|
||||
#[test]
|
||||
fn light_behind_surface() {
|
||||
// Lighting with the light behind the surface.
|
||||
let in_shadow = false;
|
||||
let m = Material::default();
|
||||
let position = point(0., 0., 0.);
|
||||
let object = Shape::sphere();
|
||||
let eyev = vector(0., 0., -1.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 0., 10.), WHITE);
|
||||
let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
assert_eq!(result, Color::new(0.1, 0.1, 0.1));
|
||||
}
|
||||
#[test]
|
||||
fn surface_in_shadow() {
|
||||
// Lighting with the surface in shadow.
|
||||
let m = Material::default();
|
||||
let position = point(0., 0., 0.);
|
||||
let object = Shape::sphere();
|
||||
let in_shadow = true;
|
||||
let eyev = vector(0., 0., -1.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
let result = lighting(&m, &object, &light, position, eyev, normalv, in_shadow);
|
||||
assert_eq!(result, Color::new(0.1, 0.1, 0.1));
|
||||
}
|
||||
#[test]
|
||||
fn pattern_applied() {
|
||||
// Lighting with a pattern applied.
|
||||
let object = Shape::sphere();
|
||||
let m = Material {
|
||||
color: Pattern::stripe(WHITE, BLACK),
|
||||
ambient: 1.,
|
||||
diffuse: 0.,
|
||||
specular: 0.,
|
||||
..Material::default()
|
||||
};
|
||||
let eyev = vector(0., 0., -1.);
|
||||
let normalv = vector(0., 0., -1.);
|
||||
let light = PointLight::new(point(0., 0., -10.), WHITE);
|
||||
let c1 = lighting(
|
||||
&m,
|
||||
&object,
|
||||
&light,
|
||||
point(0.9, 0., 0.),
|
||||
eyev,
|
||||
normalv,
|
||||
false,
|
||||
);
|
||||
let c2 = lighting(
|
||||
&m,
|
||||
&object,
|
||||
&light,
|
||||
point(1.1, 0., 0.),
|
||||
eyev,
|
||||
normalv,
|
||||
false,
|
||||
);
|
||||
assert_eq!(c1, WHITE);
|
||||
assert_eq!(c2, BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user