Add SmoothTransparentDialectric material

This commit is contained in:
Matthew Gordon 2020-09-12 10:01:33 -04:00
parent db2d1806a3
commit 7c82605d98
2 changed files with 118 additions and 0 deletions

View File

@ -15,6 +15,9 @@ pub use phong_material::PhongMaterial;
pub mod reflective_material; pub mod reflective_material;
pub use reflective_material::ReflectiveMaterial; pub use reflective_material::ReflectiveMaterial;
pub mod smooth_transparent_dialectric;
pub use smooth_transparent_dialectric::SmoothTransparentDialectric;
pub trait Material: Debug + Sync + Send { pub trait Material: Debug + Sync + Send {
fn bsdf<'a>(&'a self) -> Box<dyn Fn(&Vec3, &Vec3, &Photon) -> Photon + 'a>; fn bsdf<'a>(&'a self) -> Box<dyn Fn(&Vec3, &Vec3, &Photon) -> Photon + 'a>;

View File

@ -0,0 +1,115 @@
use crate::colour::{Photon, Spectrum};
use crate::materials::Material;
use crate::math::Vec3;
use rand::random;
#[derive(Debug)]
struct FresnelResult {
reflection_direction: Vec3,
reflection_strength: f64,
transmission_direction: Vec3,
transmission_strength: f64,
}
fn fresnel(w_i: &Vec3, eta1: f64, eta2: f64) -> FresnelResult {
let normal = if w_i.z() > 0.0 {
Vec3::unit_z()
} else {
-Vec3::unit_z()
};
let reflection_direction = Vec3::new(-w_i.x(), -w_i.y(), w_i.z());
let r = eta1 / eta2;
let cos_theta1 = normal.dot(w_i);
let cos_theta2_squared = 1.0 - r * r * (1.0 - cos_theta1 * cos_theta1);
let mut result = if cos_theta2_squared >= 0.0 {
let cos_theta2 = cos_theta2_squared.sqrt();
let reflection_strength_parallel_sqrt =
(eta1 * cos_theta2 - eta2 * cos_theta1) / (eta1 * cos_theta2 + eta2 * cos_theta1);
let reflection_strength_perpendicular_sqrt =
(eta1 * cos_theta1 - eta2 * cos_theta2) / (eta1 * cos_theta1 + eta2 * cos_theta2);
let reflection_strength = 0.5
* (reflection_strength_parallel_sqrt * reflection_strength_parallel_sqrt
+ reflection_strength_perpendicular_sqrt * reflection_strength_perpendicular_sqrt);
let transmission_direction =
(-r * w_i + (r * cos_theta1 - cos_theta2) * normal).normalize();
let transmission_strength = 1.0 - reflection_strength;
FresnelResult {
reflection_direction,
reflection_strength,
transmission_direction,
transmission_strength,
}
} else {
let reflection_strength = 1.0;
let transmission_strength = 0.0;
let transmission_direction = Default::default();
FresnelResult {
reflection_direction,
reflection_strength,
transmission_direction,
transmission_strength,
}
};
if w_i.z() < 0.0 {
result.reflection_direction.coords[2] *= -1.0;
result.transmission_direction.coords[2] *= -1.0;
}
result
}
#[derive(Debug)]
pub struct SmoothTransparentDialectric {
eta: Spectrum,
}
impl SmoothTransparentDialectric {
pub fn new(eta: Spectrum) -> SmoothTransparentDialectric {
SmoothTransparentDialectric { eta }
}
}
impl Material for SmoothTransparentDialectric {
fn bsdf<'a>(&'a self) -> Box<dyn Fn(&Vec3, &Vec3, &Photon) -> Photon + 'a> {
Box::new(move |w_o: &Vec3, w_i: &Vec3, photon_in: &Photon| {
let (eta1, eta2) = if w_i.z() >= 0.0 {
(1.0, self.eta.intensity_at_wavelength(photon_in.wavelength))
} else {
(self.eta.intensity_at_wavelength(photon_in.wavelength), 1.0)
};
let fresnel = fresnel(w_i, eta1, eta2);
if (*w_o - fresnel.reflection_direction).norm_squared() < 0.0000000001 {
photon_in.scale_intensity(fresnel.reflection_strength)
} else if (*w_o - fresnel.transmission_direction).norm_squared() < 0.0000000001 {
photon_in.scale_intensity(fresnel.transmission_strength)
} else {
/*dbg!(
w_o,
fresnel.reflection_direction,
fresnel.transmission_direction
);*/
photon_in.set_intensity(0.0)
}
})
}
fn sample(&self, w_i: &Vec3, photon: &Photon) -> Vec3 {
let (eta1, eta2) = if w_i.z() >= 0.0 {
(1.0, self.eta.intensity_at_wavelength(photon.wavelength))
} else {
(self.eta.intensity_at_wavelength(photon.wavelength), 1.0)
};
let fresnel = fresnel(w_i, eta1, eta2);
if fresnel.transmission_strength <= 0.0000000001 {
fresnel.reflection_direction
} else if fresnel.reflection_strength <= 0.0000000001 || random() {
fresnel.transmission_direction
} else {
fresnel.reflection_direction
}
}
fn pdf(&self, _w_i: &Vec3, _w_o: &Vec3) -> f64 {
0.0
}
}