pathtracer/pathtracer/src/light/directional_light.rs
Bruno BELANYI 48bb3550cb library: use beevee instead of rust-bvh
I also used this opportunity to use `nalgebra::Unit` as much as
possible.
2020-03-24 21:55:48 +01:00

94 lines
2.6 KiB
Rust

use super::{Light, SpatialLight};
use crate::core::LinearColor;
use crate::{Point, Vector};
use nalgebra::Unit;
use serde::Deserialize;
/// Represent a light emanating from a far away source, with parallel rays on all points.
#[derive(Debug, PartialEq, Deserialize)]
pub struct DirectionalLight {
#[serde(deserialize_with = "crate::serialize::vector_normalizer")]
direction: Unit<Vector>,
color: LinearColor,
}
impl DirectionalLight {
/// Creates a new `DirectionalLight`.
///
/// # Examples
///
/// ```
/// # use pathtracer::light::DirectionalLight;
/// # use pathtracer::core::color::LinearColor;
/// # use pathtracer::Vector;
/// #
/// let dir_light = DirectionalLight::new(
/// Vector::x_axis(),
/// LinearColor::new(1.0, 0.0, 1.0),
/// );
/// ```
pub fn new(direction: Unit<Vector>, color: LinearColor) -> Self {
DirectionalLight { direction, color }
}
}
impl Light for DirectionalLight {
fn illumination(&self, _: &Point) -> LinearColor {
self.color.clone()
}
}
impl SpatialLight for DirectionalLight {
fn to_source(&self, _: &Point) -> (Unit<Vector>, f32) {
(-self.direction, std::f32::INFINITY)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn new_works() {
let direction = Vector::x_axis();
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::x_axis();
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 = (
Unit::new_normalize(Vector::new(-1., 0., 0.)),
std::f32::INFINITY,
);
assert_eq!(ans, expected)
}
#[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::x_axis(), LinearColor::new(1., 0.5, 0.2))
)
}
}