2020-03-16 17:44:28 +01:00
|
|
|
use super::{Light, SpatialLight};
|
2020-03-17 20:30:50 +01:00
|
|
|
use crate::core::LinearColor;
|
|
|
|
use crate::{Point, Vector};
|
2020-03-18 14:35:53 +01:00
|
|
|
use serde::Deserialize;
|
2020-03-16 17:44:28 +01:00
|
|
|
|
|
|
|
/// Represent a light emanating from a far away source, with parallel rays on all points.
|
2020-03-18 14:35:53 +01:00
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
2020-03-16 17:44:28 +01:00
|
|
|
pub struct DirectionalLight {
|
2020-03-18 14:35:53 +01:00
|
|
|
#[serde(deserialize_with = "crate::serialize::vector_normalizer")]
|
2020-03-16 17:44:28 +01:00
|
|
|
direction: Vector,
|
|
|
|
color: LinearColor,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DirectionalLight {
|
|
|
|
pub fn new(direction: Vector, color: LinearColor) -> Self {
|
|
|
|
DirectionalLight {
|
|
|
|
direction: direction.normalize(),
|
|
|
|
color,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Light for DirectionalLight {
|
|
|
|
fn illumination(&self, _: &Point) -> LinearColor {
|
|
|
|
self.color.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SpatialLight for DirectionalLight {
|
|
|
|
fn to_source(&self, _: &Point) -> (Vector, f32) {
|
|
|
|
(self.direction * -1., std::f32::INFINITY)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn new_works() {
|
|
|
|
let direction = Vector::new(1., 0., 0.);
|
|
|
|
let color = LinearColor::new(1., 1., 1.);
|
|
|
|
let light = DirectionalLight::new(direction, color.clone());
|
|
|
|
let res = DirectionalLight { direction, color };
|
|
|
|
assert_eq!(light, res)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn simple_light() -> impl SpatialLight {
|
|
|
|
let direction = Vector::new(1., 0., 0.);
|
|
|
|
let color = LinearColor::new(1., 1., 1.);
|
|
|
|
DirectionalLight::new(direction, color)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn illumination_is_correct() {
|
|
|
|
let light = simple_light();
|
|
|
|
let lum = light.illumination(&Point::new(1., 1., 1.));
|
|
|
|
assert_eq!(lum, LinearColor::new(1., 1., 1.))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn to_source_is_correct() {
|
|
|
|
let light = simple_light();
|
|
|
|
let ans = light.to_source(&Point::new(1., 0., 0.));
|
|
|
|
let expected = (Vector::new(-1., 0., 0.), std::f32::INFINITY);
|
|
|
|
assert_eq!(ans, expected)
|
|
|
|
}
|
2020-03-18 14:35:53 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn deserialization_works() {
|
|
|
|
let yaml = "{direction: [1.0, 0.0, 0.0], color: {r: 1.0, g: 0.5, b: 0.2}}";
|
|
|
|
let light: DirectionalLight = serde_yaml::from_str(yaml).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
light,
|
|
|
|
DirectionalLight::new(Vector::new(1., 0., 0.), LinearColor::new(1., 0.5, 0.2))
|
|
|
|
)
|
|
|
|
}
|
2020-03-16 17:44:28 +01:00
|
|
|
}
|