Implement importance sampling for materials
This commit is contained in:
parent
7c82605d98
commit
45cf4fa487
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::math::Vec3;
|
use crate::math::Vec3;
|
||||||
|
|
||||||
use super::colour::{ColourRgbF, Photon, Spectrum};
|
use super::colour::{ColourRgbF, Photon, Spectrum};
|
||||||
|
use super::materials::MaterialSampleResult;
|
||||||
use super::raycasting::{IntersectionInfo, Ray};
|
use super::raycasting::{IntersectionInfo, Ray};
|
||||||
use super::sampler::Sampler;
|
use super::sampler::Sampler;
|
||||||
use super::util::algebra_utils::try_change_of_basis_matrix;
|
use super::util::algebra_utils::try_change_of_basis_matrix;
|
||||||
|
|
@ -59,7 +60,7 @@ impl Integrator for WhittedIntegrator {
|
||||||
.material
|
.material
|
||||||
.sample(&(world_to_bsdf_space * info.retro), &photon)]
|
.sample(&(world_to_bsdf_space * info.retro), &photon)]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|direction| {
|
.map(|MaterialSampleResult { direction, pdf: _ }| {
|
||||||
let world_space_direction = bsdf_to_world_space * direction;
|
let world_space_direction = bsdf_to_world_space * direction;
|
||||||
match sampler
|
match sampler
|
||||||
.sample(&Ray::new(info.location, world_space_direction).bias(0.000_000_1))
|
.sample(&Ray::new(info.location, world_space_direction).bias(0.000_000_1))
|
||||||
|
|
@ -118,11 +119,14 @@ impl Integrator for SimpleRandomIntegrator {
|
||||||
.expect("Expected matrix to be invertable.");
|
.expect("Expected matrix to be invertable.");
|
||||||
let world_space_w_i = info.retro;
|
let world_space_w_i = info.retro;
|
||||||
let w_i = world_to_bsdf_space * world_space_w_i;
|
let w_i = world_to_bsdf_space * world_space_w_i;
|
||||||
let w_o = info.material.sample(&w_i, &photon);
|
let MaterialSampleResult {
|
||||||
|
direction: w_o,
|
||||||
|
pdf: w_o_pdf,
|
||||||
|
} = info.material.sample(&w_i, &photon);
|
||||||
let world_space_w_o = bsdf_to_world_space * w_o;
|
let world_space_w_o = bsdf_to_world_space * w_o;
|
||||||
info.material.bsdf()(
|
info.material.bsdf()(
|
||||||
&w_o.normalize(),
|
&w_o,
|
||||||
&w_i.normalize(),
|
&w_i,
|
||||||
&match sampler.sample(&Ray::new(info.location, world_space_w_o).bias(0.000_000_1)) {
|
&match sampler.sample(&Ray::new(info.location, world_space_w_o).bias(0.000_000_1)) {
|
||||||
None => photon.set_intensity(test_lighting_environment(
|
None => photon.set_intensity(test_lighting_environment(
|
||||||
&world_space_w_o,
|
&world_space_w_o,
|
||||||
|
|
@ -132,6 +136,7 @@ impl Integrator for SimpleRandomIntegrator {
|
||||||
self.integrate(&sampler, &recursive_hit, &photon, recursion_limit - 1)
|
self.integrate(&sampler, &recursive_hit, &photon, recursion_limit - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.scale_intensity(w_o_pdf)
|
||||||
.scale_intensity(world_space_w_o.dot(&info.normal).abs()),
|
.scale_intensity(world_space_w_o.dot(&info.normal).abs()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +147,7 @@ pub fn test_lighting_environment(w_o: &Vec3, wavelength: f64) -> f64 {
|
||||||
if w_o.dot(&sun_direction) >= 0.99 {
|
if w_o.dot(&sun_direction) >= 0.99 {
|
||||||
300.0
|
300.0
|
||||||
} else {
|
} else {
|
||||||
let sky_colour = ColourRgbF::new(w_o.y(), w_o.y(), 1.0) * 0.1;
|
let sky_colour = ColourRgbF::new(w_o.y(), w_o.y(), 1.0);
|
||||||
Spectrum::reflection_from_linear_rgb(&sky_colour).intensity_at_wavelength(wavelength)
|
Spectrum::reflection_from_linear_rgb(&sky_colour).intensity_at_wavelength(wavelength)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
use crate::colour::{Photon, Spectrum};
|
use crate::colour::{Photon, Spectrum};
|
||||||
use crate::math::Vec3;
|
use crate::math::Vec3;
|
||||||
|
|
||||||
use super::Material;
|
use super::{Material, MaterialSampleResult};
|
||||||
|
|
||||||
|
use rand::distributions::Open01;
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
|
use std::f64::consts::PI;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -28,4 +32,29 @@ impl Material for LambertianMaterial {
|
||||||
result
|
result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sample(&self, _w_i: &Vec3, _photon: &Photon) -> MaterialSampleResult {
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
let mut w_o = Vec3::new(
|
||||||
|
2.0 * rng.sample::<f64, _>(Open01) - 1.0,
|
||||||
|
2.0 * rng.sample::<f64, _>(Open01) - 1.0,
|
||||||
|
0.0,
|
||||||
|
);
|
||||||
|
while w_o.norm_squared() > 1.0 {
|
||||||
|
w_o = Vec3::new(
|
||||||
|
2.0 * rng.sample::<f64, _>(Open01) - 1.0,
|
||||||
|
2.0 * rng.sample::<f64, _>(Open01) - 1.0,
|
||||||
|
0.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
w_o.coords[2] = (1.0 - w_o.x() * w_o.x() - w_o.y() * w_o.y())
|
||||||
|
.sqrt()
|
||||||
|
.max(0.0);
|
||||||
|
let cos_theta = w_o.dot(&Vec3::unit_z());
|
||||||
|
let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();
|
||||||
|
MaterialSampleResult {
|
||||||
|
direction: w_o.normalize(),
|
||||||
|
pdf: (cos_theta * sin_theta) / PI,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use super::colour::Photon;
|
||||||
|
|
||||||
use rand::distributions::{Open01, OpenClosed01};
|
use rand::distributions::{Open01, OpenClosed01};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
use std::f64::consts::PI;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub mod lambertian_material;
|
pub mod lambertian_material;
|
||||||
|
|
@ -18,10 +19,15 @@ pub use reflective_material::ReflectiveMaterial;
|
||||||
pub mod smooth_transparent_dialectric;
|
pub mod smooth_transparent_dialectric;
|
||||||
pub use smooth_transparent_dialectric::SmoothTransparentDialectric;
|
pub use smooth_transparent_dialectric::SmoothTransparentDialectric;
|
||||||
|
|
||||||
|
pub struct MaterialSampleResult {
|
||||||
|
pub direction: Vec3,
|
||||||
|
pub pdf: f64,
|
||||||
|
}
|
||||||
|
|
||||||
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>;
|
||||||
|
|
||||||
fn sample(&self, _w_i: &Vec3, _photon: &Photon) -> Vec3 {
|
fn sample(&self, _w_i: &Vec3, _photon: &Photon) -> MaterialSampleResult {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let mut w_o = Vec3::new(
|
let mut w_o = Vec3::new(
|
||||||
2.0 * rng.sample::<f64, _>(Open01) - 1.0,
|
2.0 * rng.sample::<f64, _>(Open01) - 1.0,
|
||||||
|
|
@ -35,10 +41,9 @@ pub trait Material: Debug + Sync + Send {
|
||||||
rng.sample::<f64, _>(OpenClosed01),
|
rng.sample::<f64, _>(OpenClosed01),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
w_o
|
MaterialSampleResult {
|
||||||
}
|
direction: w_o.normalize(),
|
||||||
|
pdf: 1.0 / (2.0 * PI),
|
||||||
fn pdf(&self, _w_i: &Vec3, _w_o: &Vec3) -> f64 {
|
}
|
||||||
1.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use crate::math::Vec3;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use super::Material;
|
use super::{Material, MaterialSampleResult};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ReflectiveMaterial {
|
pub struct ReflectiveMaterial {
|
||||||
|
|
@ -39,7 +39,10 @@ impl Material for ReflectiveMaterial {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample(&self, w_o: &Vec3, _photon: &Photon) -> Vec3 {
|
fn sample(&self, w_o: &Vec3, _photon: &Photon) -> MaterialSampleResult {
|
||||||
Vec3::new(-w_o.x(), -w_o.y(), w_o.z())
|
MaterialSampleResult {
|
||||||
|
direction: Vec3::new(-w_o.x(), -w_o.y(), w_o.z()),
|
||||||
|
pdf: 1.0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::colour::{Photon, Spectrum};
|
use crate::colour::{Photon, Spectrum};
|
||||||
use crate::materials::Material;
|
use crate::materials::{Material, MaterialSampleResult};
|
||||||
use crate::math::Vec3;
|
use crate::math::Vec3;
|
||||||
|
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
|
@ -83,17 +83,12 @@ impl Material for SmoothTransparentDialectric {
|
||||||
} else if (*w_o - fresnel.transmission_direction).norm_squared() < 0.0000000001 {
|
} else if (*w_o - fresnel.transmission_direction).norm_squared() < 0.0000000001 {
|
||||||
photon_in.scale_intensity(fresnel.transmission_strength)
|
photon_in.scale_intensity(fresnel.transmission_strength)
|
||||||
} else {
|
} else {
|
||||||
/*dbg!(
|
|
||||||
w_o,
|
|
||||||
fresnel.reflection_direction,
|
|
||||||
fresnel.transmission_direction
|
|
||||||
);*/
|
|
||||||
photon_in.set_intensity(0.0)
|
photon_in.set_intensity(0.0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample(&self, w_i: &Vec3, photon: &Photon) -> Vec3 {
|
fn sample(&self, w_i: &Vec3, photon: &Photon) -> MaterialSampleResult {
|
||||||
let (eta1, eta2) = if w_i.z() >= 0.0 {
|
let (eta1, eta2) = if w_i.z() >= 0.0 {
|
||||||
(1.0, self.eta.intensity_at_wavelength(photon.wavelength))
|
(1.0, self.eta.intensity_at_wavelength(photon.wavelength))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -101,15 +96,20 @@ impl Material for SmoothTransparentDialectric {
|
||||||
};
|
};
|
||||||
let fresnel = fresnel(w_i, eta1, eta2);
|
let fresnel = fresnel(w_i, eta1, eta2);
|
||||||
if fresnel.transmission_strength <= 0.0000000001 {
|
if fresnel.transmission_strength <= 0.0000000001 {
|
||||||
fresnel.reflection_direction
|
MaterialSampleResult {
|
||||||
|
direction: fresnel.reflection_direction,
|
||||||
|
pdf: 0.5,
|
||||||
|
}
|
||||||
} else if fresnel.reflection_strength <= 0.0000000001 || random() {
|
} else if fresnel.reflection_strength <= 0.0000000001 || random() {
|
||||||
fresnel.transmission_direction
|
MaterialSampleResult {
|
||||||
|
direction: fresnel.transmission_direction,
|
||||||
|
pdf: 0.5,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fresnel.reflection_direction
|
MaterialSampleResult {
|
||||||
|
direction: fresnel.reflection_direction,
|
||||||
|
pdf: 0.5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pdf(&self, _w_i: &Vec3, _w_o: &Vec3) -> f64 {
|
|
||||||
0.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue