Add dielectric pbrt material
This commit is contained in:
parent
0480e041cd
commit
2269bd102d
5 changed files with 43 additions and 27 deletions
15
ray-tracing-core/src/math/material.rs
Normal file
15
ray-tracing-core/src/math/material.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub 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)
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod dir3;
|
pub mod dir3;
|
||||||
pub mod frame;
|
pub mod frame;
|
||||||
pub mod mat3;
|
pub mod mat3;
|
||||||
|
pub mod material;
|
||||||
pub mod pos3;
|
pub mod pos3;
|
||||||
pub mod sampling;
|
pub mod sampling;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use plotters::prelude::*;
|
use plotters::prelude::*;
|
||||||
use ray_tracing_core::prelude::*;
|
use ray_tracing_core::{math::material::fresnel_real, prelude::*};
|
||||||
use ray_tracing_material::microfacet::fresnel_real;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let root = BitMapBackend::new("fresnel.png", (640, 480)).into_drawing_area();
|
let root = BitMapBackend::new("fresnel.png", (640, 480)).into_drawing_area();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use rand_distr::{Distribution, Normal};
|
use rand_distr::{Distribution, Normal};
|
||||||
use ray_tracing_core::{material::Material, prelude::*};
|
use ray_tracing_core::{material::Material, math::material::fresnel_real, prelude::*};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -14,20 +14,6 @@ impl<D: MicrofacetDistribution + Debug> Microfacet<D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub 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 + Send> Material<R> for Microfacet<D> {
|
impl<R: Rng, D: MicrofacetDistribution + Debug + Sync + Send> Material<R> for Microfacet<D> {
|
||||||
fn eval(&self, w_in: Dir3, w_out: Dir3, _rng: &mut R) -> ray_tracing_core::prelude::Color {
|
fn eval(&self, w_in: Dir3, w_out: Dir3, _rng: &mut R) -> ray_tracing_core::prelude::Color {
|
||||||
if w_out.y() > 0.0 && w_in.y() > 0.0 {
|
if w_out.y() > 0.0 && w_in.y() > 0.0 {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
use ray_tracing_core::{color::Color, material::SampleResult, prelude::*};
|
use ray_tracing_core::{
|
||||||
|
color::Color, material::SampleResult, math::material::fresnel_real, prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
either::Either,
|
either::Either,
|
||||||
|
|
@ -103,20 +105,33 @@ impl<R: Rng> PbrtMaterial<R> for PbrtDielectricMaterial {
|
||||||
let _ = rng;
|
let _ = rng;
|
||||||
let _ = v;
|
let _ = v;
|
||||||
let _ = u;
|
let _ = u;
|
||||||
let _ = match self.eta {
|
let eta = match self.eta {
|
||||||
Either::A(Either::A(eta)) => eta,
|
Either::A(Either::A(eta)) => eta,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// let c = w_in.y();
|
let (n1, n2) = if w_in.y() >= 0.0 {
|
||||||
// let w_out = -w_in * eta
|
(1.0, eta)
|
||||||
// + (eta * c - Float::sqrt(1.0 - eta * eta * (1.0 - c * c))) * Dir3::new(0.0, -1.0, 1.0);
|
} else {
|
||||||
|
(eta, 1.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
let r = fresnel_real(w_in.y().abs(), n1, n2);
|
||||||
|
|
||||||
|
if r >= rng.r#gen() {
|
||||||
SampleResult::new(
|
SampleResult::new(
|
||||||
Dir3::new(0.0, 2.0 * w_in.y(), 0.0) - w_in,
|
Dir3::new(0.0, 2.0 * w_in.y(), 0.0) - w_in,
|
||||||
Color::white(),
|
Color::white(),
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
let r = n1 / n2;
|
||||||
|
let w_out = -w_in * r
|
||||||
|
+ (r * w_in.y().abs() - Float::sqrt(1.0 - r * r * (1.0 - w_in.y() * w_in.y())))
|
||||||
|
* Dir3::new(0.0, if w_in.y() > 0.0 { 1.0 } else { -1.0 }, 0.0);
|
||||||
|
|
||||||
|
SampleResult::new(w_out, Color::white(), true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pdf(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3) -> Float {
|
fn pdf(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3) -> Float {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue