pathtracer/src/core/light_properties.rs
Bruno BELANYI 552c0cb966 library: implement refraction
This necessitated to rework how light properties for a material were
given. A material can have either reflectivity or transparency. This
changes the parsing of materials, using a `LightProperty` structure at
its core.

This is does not implement the true Fresnel equations to take into
account the amount of reflection that an incident goes through when
encountering a transparent object.
2020-03-19 18:23:20 +01:00

125 lines
3.4 KiB
Rust

use super::color::LinearColor;
use serde::Deserialize;
#[derive(Debug, PartialEq, Clone, Deserialize)]
#[serde(untagged)]
pub enum ReflTransEnum {
Transparency {
/// The transparency coefficient.
#[serde(rename = "transparency")]
coef: f32,
/// The diffraction index.
index: f32,
},
Reflectivity {
/// The reflectivity coefficient.
#[serde(rename = "reflectivity")]
coef: f32,
},
}
/// A structure holding all the physical proprerties relating to light at a point.
#[derive(Debug, PartialEq, Clone, Deserialize)]
pub struct LightProperties {
/// The diffuse component.
pub diffuse: LinearColor,
/// The specular component.
pub specular: LinearColor,
/// The transparency or reflectivity properties.
#[serde(flatten)]
pub refl_trans: Option<ReflTransEnum>,
}
impl LightProperties {
pub fn new(
diffuse: LinearColor,
specular: LinearColor,
refl_trans: Option<ReflTransEnum>,
) -> Self {
LightProperties {
diffuse,
specular,
refl_trans,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn new_works() {
let diffuse = LinearColor::new(0.25, 0.5, 1.);
let specular = LinearColor::new(0.75, 0.375, 0.125);
let refl_trans = Some(ReflTransEnum::Reflectivity { coef: 0.5 });
let properties =
LightProperties::new(diffuse.clone(), specular.clone(), refl_trans.clone());
assert_eq!(
properties,
LightProperties {
diffuse,
specular,
refl_trans,
}
)
}
#[test]
fn deserialization_without_refl_trans_works() {
let yaml = r#"
diffuse: {r: 1.0, g: 0.5, b: 0.25}
specular: {r: 0.25, g: 0.125, b: 0.75}
"#;
let properties: LightProperties = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
properties,
LightProperties::new(
LinearColor::new(1., 0.5, 0.25),
LinearColor::new(0.25, 0.125, 0.75),
None
)
)
}
#[test]
fn deserialization_with_reflection_works() {
let yaml = r#"
diffuse: {r: 1.0, g: 0.5, b: 0.25}
specular: {r: 0.25, g: 0.125, b: 0.75}
transparency: 0.5
index: 1.5
"#;
let properties: LightProperties = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
properties,
LightProperties::new(
LinearColor::new(1., 0.5, 0.25),
LinearColor::new(0.25, 0.125, 0.75),
Some(ReflTransEnum::Transparency {
coef: 0.5,
index: 1.5
})
)
)
}
#[test]
fn deserialization_with_transparency_works() {
let yaml = r#"
diffuse: {r: 1.0, g: 0.5, b: 0.25}
specular: {r: 0.25, g: 0.125, b: 0.75}
reflectivity: 0.25
"#;
let properties: LightProperties = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
properties,
LightProperties::new(
LinearColor::new(1., 0.5, 0.25),
LinearColor::new(0.25, 0.125, 0.75),
Some(ReflTransEnum::Reflectivity { coef: 0.25 })
)
)
}
}