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 {
|
impl Default for Material {
|
||||||
/// Creates the default 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 {
|
fn default() -> Material {
|
||||||
Material {
|
Material {
|
||||||
color: WHITE.into(),
|
color: WHITE.into(),
|
||||||
@ -59,99 +39,6 @@ impl Default for Material {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute lighting contributions using the Phong reflection model.
|
/// 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(
|
pub fn lighting(
|
||||||
material: &Material,
|
material: &Material,
|
||||||
object: &Shape,
|
object: &Shape,
|
||||||
@ -197,3 +84,153 @@ pub fn lighting(
|
|||||||
ambient + diffuse + specular
|
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