Add Oren-Nayar and fix bugs
This commit is contained in:
parent
3a37a72f56
commit
745b7d2602
7 changed files with 137 additions and 28 deletions
|
|
@ -14,7 +14,11 @@ impl DiffuseMaterial {
|
|||
}
|
||||
|
||||
impl<R: Rng> Material<R> for DiffuseMaterial {
|
||||
fn eval(&self, _w_in: Dir3, _w_out: Dir3, _rng: &mut R) -> Color {
|
||||
self.albedo
|
||||
fn eval(&self, _w_in: Dir3, w_out: Dir3, _rng: &mut R) -> Color {
|
||||
if w_out.y() >= 0.0 {
|
||||
self.albedo
|
||||
} else {
|
||||
Color::black()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ pub mod default;
|
|||
pub mod diffuse;
|
||||
pub mod microfacet;
|
||||
pub mod mirror;
|
||||
pub mod oren_nayar;
|
||||
|
|
|
|||
|
|
@ -2,34 +2,57 @@ use ray_tracing_core::{material::Material, prelude::*};
|
|||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Microfacet<D: MicrofacetDistribution + Debug> {
|
||||
pub struct Microfacet<D: MicrofacetDistribution + Debug> {
|
||||
dist: D,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
fn fresnel(w_in: Dir3, n: Dir3, nu_rel: Float) -> Float {
|
||||
todo!()
|
||||
}
|
||||
|
||||
impl<R: Rng, D: MicrofacetDistribution + Debug + Sync> Material<R> for Microfacet<D> {
|
||||
fn eval(
|
||||
&self,
|
||||
w_in: ray_tracing_core::prelude::Dir3,
|
||||
w_out: ray_tracing_core::prelude::Dir3,
|
||||
_rng: &mut R,
|
||||
) -> ray_tracing_core::prelude::Color {
|
||||
let w_h = (w_in + w_out).normalize();
|
||||
|
||||
let g = self.dist.g1(w_in, w_h) * self.dist.g1(w_out, w_h);
|
||||
|
||||
self.color * fresnel(w_in, w_h, 1.0) * g * self.dist.d(w_h) / (4.0 * w_in.y() * w_out.y())
|
||||
impl<D: MicrofacetDistribution + Debug> Microfacet<D> {
|
||||
pub fn new(dist: D, color: Color) -> Self {
|
||||
Self { dist, color }
|
||||
}
|
||||
}
|
||||
|
||||
struct BeckmannDistribution {
|
||||
fn fresnel_real(cos_theta_in: Float, nu1: Float, nu2: Float) -> Float {
|
||||
let nu_rel = nu1 / nu2;
|
||||
let cos_theta_tr = Float::sqrt(1.0 - nu_rel * nu_rel * (1.0 - cos_theta_in * cos_theta_in));
|
||||
|
||||
let rs = ((nu1 * cos_theta_in - nu2 * cos_theta_tr)
|
||||
/ (nu1 * cos_theta_in + nu2 * cos_theta_tr))
|
||||
.powi(2);
|
||||
let rp = ((nu1 * cos_theta_tr - nu2 * cos_theta_in)
|
||||
/ (nu1 * cos_theta_tr + nu2 * cos_theta_in))
|
||||
.powi(2);
|
||||
|
||||
0.5 * (rs + rp)
|
||||
}
|
||||
|
||||
impl<R: Rng, D: MicrofacetDistribution + Debug + Sync> Material<R> for Microfacet<D> {
|
||||
fn eval(&self, w_in: Dir3, w_out: Dir3, _rng: &mut R) -> ray_tracing_core::prelude::Color {
|
||||
if w_out.y() > 0.0 {
|
||||
let w_h = (w_in + w_out).normalize();
|
||||
|
||||
let g = self.dist.g1(w_in, w_h) * self.dist.g1(w_out, w_h);
|
||||
|
||||
self.color * fresnel_real(Dir3::dot(w_in, w_h), 1.0, 1.3) * g * self.dist.d(w_h)
|
||||
/ (4.0 * w_in.y() * w_out.y()).max(0.0)
|
||||
} else {
|
||||
Color::black()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BeckmannDistribution {
|
||||
alpha: Float,
|
||||
}
|
||||
|
||||
impl BeckmannDistribution {
|
||||
pub fn new(alpha: Float) -> Self {
|
||||
Self { alpha }
|
||||
}
|
||||
}
|
||||
|
||||
impl MicrofacetDistribution for BeckmannDistribution {
|
||||
fn g1(&self, w: Dir3, w_h: Dir3) -> Float {
|
||||
if w.y() > 0.0 && Dir3::dot(w, w_h) > 0.0 {
|
||||
|
|
@ -55,7 +78,7 @@ impl MicrofacetDistribution for BeckmannDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
trait MicrofacetDistribution {
|
||||
pub trait MicrofacetDistribution {
|
||||
fn g1(&self, w: Dir3, w_h: Dir3) -> Float;
|
||||
|
||||
fn d(&self, w_h: Dir3) -> Float;
|
||||
|
|
|
|||
39
ray-tracing-material/src/oren_nayar.rs
Normal file
39
ray-tracing-material/src/oren_nayar.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use ray_tracing_core::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OrenNayar {
|
||||
rho: Float,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl OrenNayar {
|
||||
pub fn new(rho: Float, color: Color) -> Self {
|
||||
Self { rho, color }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Rng> Material<R> for OrenNayar {
|
||||
fn eval(&self, w_in: Dir3, w_out: Dir3, _rng: &mut R) -> Color {
|
||||
if w_out.y() > 0.0 {
|
||||
let cos_alpha = Float::min(w_in.y(), w_out.y());
|
||||
let cos_beta = Float::max(w_in.y(), w_out.y());
|
||||
|
||||
let a = 1.0 - (self.rho * self.rho) / (2.0 * self.rho * self.rho + 0.33);
|
||||
let b = 0.45 * self.rho * self.rho / (self.rho * self.rho + 0.09);
|
||||
|
||||
let sin_alpha = Float::sqrt(1.0 - cos_alpha * cos_alpha);
|
||||
let tan_beta = Float::sqrt(1.0 - cos_beta * cos_beta) / cos_beta;
|
||||
|
||||
let w_in_tick = w_in - Dir3::up() * w_in.y();
|
||||
let w_out_tick = w_out - Dir3::up() * w_out.y();
|
||||
|
||||
let cos_phi = Dir3::dot(w_in_tick, w_out_tick);
|
||||
|
||||
self.color
|
||||
* FloatConsts::FRAC_1_PI
|
||||
* (a + b * Float::max(0.0, cos_phi) * sin_alpha * tan_beta)
|
||||
} else {
|
||||
Color::black()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue