Add random_distributions::SkyLightPdf

This commit is contained in:
Matthew Gordon 2021-10-08 08:37:29 -04:00
parent ed224b18cb
commit 6a1fe84af7
2 changed files with 68 additions and 0 deletions

View File

@ -13,6 +13,9 @@ pub use cosine_weighted_hemisphere::CosineWeightedHemisphere;
mod linear_weighted; mod linear_weighted;
pub use linear_weighted::LinearWeighted; pub use linear_weighted::LinearWeighted;
mod sky_light_pdf;
pub use sky_light_pdf::SkyLightPdf;
pub trait RandomDistribution<T> { pub trait RandomDistribution<T> {
fn value(&self) -> T; fn value(&self) -> T;
fn pdf(&self, value: T) -> f64; fn pdf(&self, value: T) -> f64;

View File

@ -0,0 +1,65 @@
use std::f64::consts::PI;
use rand::distributions::Open01;
use rand::{thread_rng, Rng};
use crate::math::Vec3;
use super::{LinearWeighted, RandomDistribution};
pub struct SkyLightPdf {
z_distribution: LinearWeighted,
}
impl SkyLightPdf {
pub fn new() -> SkyLightPdf {
let z_distribution = LinearWeighted::new(1.0);
SkyLightPdf { z_distribution }
}
}
impl RandomDistribution<Vec3> for SkyLightPdf {
fn value(&self) -> Vec3 {
let mut rng = thread_rng();
let phi = rng.sample::<f64, _>(Open01) * 2.0 * PI;
let z = self.z_distribution.value();
let r = (1.0 - z * z).sqrt();
Vec3::new(r * phi.cos(), r * phi.sin(), z)
}
fn pdf(&self, value: Vec3) -> f64 {
let z = value.z();
if z < 0.0 {
0.0
} else {
z / PI
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn print_values() {
let target = SkyLightPdf::new();
for _ in 0..1000 {
let value = target.value();
println!("{}, {}, {}", value.x(), value.y(), value.z());
}
}
#[test]
#[ignore]
fn integral_is_near_area() {
let target = SkyLightPdf::new();
let integral = (0..100000)
.map(|_| target.value())
.map(|value| 1.0 / target.pdf(value))
.sum::<f64>()
/ 100000.0;
println!("Area: {}\nIntegral: {}", 2.0 * PI, integral);
}
}