Some refactoring in preparation for a material system.
The main change is that SurfaceClosures now have the hero wavelength baked into them. Since surface closures come from surface intersections, and intersections are always specific to a ray or path, and rays/paths have a fixed wavelength, it doesn't make sense for the surface closure to constantly be converting from a more general color representation to spectral samples whenever its used. This is also nice because it keeps surface closures removed from any particular representation of color. All color space handling etc. can be kept inside the shaders.
This commit is contained in:
parent
6413308c7c
commit
f4d4152543
|
@ -69,7 +69,7 @@ impl<'a> Camera<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_ray(&self, x: f32, y: f32, time: f32, u: f32, v: f32) -> Ray {
|
pub fn generate_ray(&self, x: f32, y: f32, time: f32, wavelength: f32, u: f32, v: f32) -> Ray {
|
||||||
// Get time-interpolated camera settings
|
// Get time-interpolated camera settings
|
||||||
let transform = lerp_slice(self.transforms, time);
|
let transform = lerp_slice(self.transforms, time);
|
||||||
let tfov = lerp_slice(self.tfovs, time);
|
let tfov = lerp_slice(self.tfovs, time);
|
||||||
|
@ -89,6 +89,6 @@ impl<'a> Camera<'a> {
|
||||||
1.0,
|
1.0,
|
||||||
).normalized();
|
).normalized();
|
||||||
|
|
||||||
Ray::new(orig * transform, dir * transform, time, false)
|
Ray::new(orig * transform, dir * transform, time, wavelength, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,19 @@ pub struct Ray {
|
||||||
pub dir: Vector,
|
pub dir: Vector,
|
||||||
pub max_t: f32,
|
pub max_t: f32,
|
||||||
pub time: f32,
|
pub time: f32,
|
||||||
|
pub wavelength: f32,
|
||||||
pub flags: u32,
|
pub flags: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ray {
|
impl Ray {
|
||||||
pub fn new(orig: Point, dir: Vector, time: f32, is_occ: bool) -> Ray {
|
pub fn new(orig: Point, dir: Vector, time: f32, wavelength: f32, is_occ: bool) -> Ray {
|
||||||
if !is_occ {
|
if !is_occ {
|
||||||
Ray {
|
Ray {
|
||||||
orig: orig,
|
orig: orig,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
max_t: std::f32::INFINITY,
|
max_t: std::f32::INFINITY,
|
||||||
time: time,
|
time: time,
|
||||||
|
wavelength: wavelength,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,6 +36,7 @@ impl Ray {
|
||||||
dir: dir,
|
dir: dir,
|
||||||
max_t: 1.0,
|
max_t: 1.0,
|
||||||
time: time,
|
time: time,
|
||||||
|
wavelength: wavelength,
|
||||||
flags: OCCLUSION_FLAG,
|
flags: OCCLUSION_FLAG,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,6 +412,7 @@ impl LightPath {
|
||||||
image_plane_co.0,
|
image_plane_co.0,
|
||||||
image_plane_co.1,
|
image_plane_co.1,
|
||||||
time,
|
time,
|
||||||
|
wavelength,
|
||||||
lens_uv.0,
|
lens_uv.0,
|
||||||
lens_uv.1,
|
lens_uv.1,
|
||||||
),
|
),
|
||||||
|
@ -468,13 +469,8 @@ impl LightPath {
|
||||||
// Check if pdf is zero, to avoid NaN's.
|
// Check if pdf is zero, to avoid NaN's.
|
||||||
if light_pdf > 0.0 {
|
if light_pdf > 0.0 {
|
||||||
let material = closure.as_surface_closure();
|
let material = closure.as_surface_closure();
|
||||||
let attenuation = material.evaluate(
|
let attenuation =
|
||||||
ray.dir,
|
material.evaluate(ray.dir, shadow_vec, idata.nor, idata.nor_g);
|
||||||
shadow_vec,
|
|
||||||
idata.nor,
|
|
||||||
idata.nor_g,
|
|
||||||
self.wavelength,
|
|
||||||
);
|
|
||||||
|
|
||||||
if attenuation.e.h_max() > 0.0 {
|
if attenuation.e.h_max() > 0.0 {
|
||||||
// Calculate and store the light that will be contributed
|
// Calculate and store the light that will be contributed
|
||||||
|
@ -491,7 +487,13 @@ impl LightPath {
|
||||||
idata.nor_g.normalized(),
|
idata.nor_g.normalized(),
|
||||||
shadow_vec,
|
shadow_vec,
|
||||||
);
|
);
|
||||||
*ray = Ray::new(offset_pos, shadow_vec, self.time, true);
|
*ray = Ray::new(
|
||||||
|
offset_pos,
|
||||||
|
shadow_vec,
|
||||||
|
self.time,
|
||||||
|
self.wavelength,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
// For distant lights
|
// For distant lights
|
||||||
if is_infinite {
|
if is_infinite {
|
||||||
|
@ -518,13 +520,7 @@ impl LightPath {
|
||||||
let material = closure.as_surface_closure();
|
let material = closure.as_surface_closure();
|
||||||
let u = self.next_lds_samp();
|
let u = self.next_lds_samp();
|
||||||
let v = self.next_lds_samp();
|
let v = self.next_lds_samp();
|
||||||
material.sample(
|
material.sample(idata.incoming, idata.nor, idata.nor_g, (u, v))
|
||||||
idata.incoming,
|
|
||||||
idata.nor,
|
|
||||||
idata.nor_g,
|
|
||||||
(u, v),
|
|
||||||
self.wavelength,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if pdf is zero, to avoid NaN's.
|
// Check if pdf is zero, to avoid NaN's.
|
||||||
|
@ -541,7 +537,7 @@ impl LightPath {
|
||||||
dir,
|
dir,
|
||||||
);
|
);
|
||||||
self.next_bounce_ray =
|
self.next_bounce_ray =
|
||||||
Some(Ray::new(offset_pos, dir, self.time, false));
|
Some(Ray::new(offset_pos, dir, self.time, self.wavelength, false));
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,14 +2,15 @@ pub mod surface_closure;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use self::surface_closure::SurfaceClosureUnion;
|
use color::{XYZ, Color};
|
||||||
|
use self::surface_closure::{SurfaceClosureUnion, EmitClosure, LambertClosure, GTRClosure};
|
||||||
use surface::SurfaceIntersectionData;
|
use surface::SurfaceIntersectionData;
|
||||||
|
|
||||||
/// Trait for surface shaders.
|
/// Trait for surface shaders.
|
||||||
pub trait SurfaceShader: Debug {
|
pub trait SurfaceShader: Debug {
|
||||||
/// Takes the result of a surface intersection and returns the surface
|
/// Takes the result of a surface intersection and returns the surface
|
||||||
/// closure to be evaluated at that intersection point.
|
/// closure to be evaluated at that intersection point.
|
||||||
fn shade(&self, data: &SurfaceIntersectionData) -> SurfaceClosureUnion;
|
fn shade(&self, data: &SurfaceIntersectionData, wavelength: f32) -> SurfaceClosureUnion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clearly we must eat this brownie before the world ends, lest it
|
/// Clearly we must eat this brownie before the world ends, lest it
|
||||||
|
@ -24,19 +25,45 @@ pub trait SurfaceShader: Debug {
|
||||||
/// them a great injustice, for they are each the size of a small
|
/// them a great injustice, for they are each the size of a small
|
||||||
/// building.
|
/// building.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SimpleSurfaceShader {
|
pub enum SimpleSurfaceShader {
|
||||||
closure: SurfaceClosureUnion,
|
Emit { color: XYZ },
|
||||||
}
|
Lambert { color: XYZ },
|
||||||
|
GTR {
|
||||||
impl SimpleSurfaceShader {
|
color: XYZ,
|
||||||
fn new(closure: SurfaceClosureUnion) -> SimpleSurfaceShader {
|
roughness: f32,
|
||||||
SimpleSurfaceShader { closure: closure }
|
tail_shape: f32,
|
||||||
}
|
fresnel: f32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SurfaceShader for SimpleSurfaceShader {
|
impl SurfaceShader for SimpleSurfaceShader {
|
||||||
fn shade(&self, data: &SurfaceIntersectionData) -> SurfaceClosureUnion {
|
fn shade(&self, data: &SurfaceIntersectionData, wavelength: f32) -> SurfaceClosureUnion {
|
||||||
let _ = data; // Silence "unused" compiler warning
|
let _ = data; // Silence "unused" compiler warning
|
||||||
self.closure
|
|
||||||
|
match *self {
|
||||||
|
SimpleSurfaceShader::Emit { color } => {
|
||||||
|
SurfaceClosureUnion::EmitClosure(
|
||||||
|
EmitClosure::new(color.to_spectral_sample(wavelength)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SimpleSurfaceShader::Lambert { color } => {
|
||||||
|
SurfaceClosureUnion::LambertClosure(
|
||||||
|
LambertClosure::new(color.to_spectral_sample(wavelength)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SimpleSurfaceShader::GTR {
|
||||||
|
color,
|
||||||
|
roughness,
|
||||||
|
tail_shape,
|
||||||
|
fresnel,
|
||||||
|
} => {
|
||||||
|
SurfaceClosureUnion::GTRClosure(GTRClosure::new(
|
||||||
|
color.to_spectral_sample(wavelength),
|
||||||
|
roughness,
|
||||||
|
tail_shape,
|
||||||
|
fresnel,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::f32::consts::PI as PI_32;
|
use std::f32::consts::PI as PI_32;
|
||||||
|
|
||||||
use color::{XYZ, SpectralSample, Color};
|
use color::SpectralSample;
|
||||||
use math::{Vector, Normal, dot, clamp, zup_to_vec};
|
use math::{Vector, Normal, dot, clamp, zup_to_vec};
|
||||||
use sampling::cosine_sample_hemisphere;
|
use sampling::cosine_sample_hemisphere;
|
||||||
use lerp::lerp;
|
use lerp::lerp;
|
||||||
|
@ -29,6 +29,10 @@ impl SurfaceClosureUnion {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for surface closures.
|
/// Trait for surface closures.
|
||||||
|
///
|
||||||
|
/// Note: each surface closure is assumed to be bound to a particular hero
|
||||||
|
/// wavelength. This is implicit in the `sample`, `evaluate`, and `sample_pdf`
|
||||||
|
/// functions below.
|
||||||
pub trait SurfaceClosure {
|
pub trait SurfaceClosure {
|
||||||
/// Returns whether the closure has a delta distribution or not.
|
/// Returns whether the closure has a delta distribution or not.
|
||||||
fn is_delta(&self) -> bool;
|
fn is_delta(&self) -> bool;
|
||||||
|
@ -40,7 +44,6 @@ pub trait SurfaceClosure {
|
||||||
/// nor: The shading surface normal at the surface point.
|
/// nor: The shading surface normal at the surface point.
|
||||||
/// nor_g: The geometric surface normal at the surface point.
|
/// nor_g: The geometric surface normal at the surface point.
|
||||||
/// uv: The sampling values.
|
/// uv: The sampling values.
|
||||||
/// wavelength: The wavelength of light to sample at.
|
|
||||||
///
|
///
|
||||||
/// Returns a tuple with the generated outgoing light direction, color filter, and pdf.
|
/// Returns a tuple with the generated outgoing light direction, color filter, and pdf.
|
||||||
fn sample(
|
fn sample(
|
||||||
|
@ -49,7 +52,6 @@ pub trait SurfaceClosure {
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
nor_g: Normal,
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
|
||||||
) -> (Vector, SpectralSample, f32);
|
) -> (Vector, SpectralSample, f32);
|
||||||
|
|
||||||
/// Evaluates the closure for the given incoming and outgoing rays.
|
/// Evaluates the closure for the given incoming and outgoing rays.
|
||||||
|
@ -61,14 +63,7 @@ pub trait SurfaceClosure {
|
||||||
/// wavelength: The wavelength of light to evaluate for.
|
/// wavelength: The wavelength of light to evaluate for.
|
||||||
///
|
///
|
||||||
/// Returns the resulting filter color.
|
/// Returns the resulting filter color.
|
||||||
fn evaluate(
|
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> SpectralSample;
|
||||||
&self,
|
|
||||||
inc: Vector,
|
|
||||||
out: Vector,
|
|
||||||
nor: Normal,
|
|
||||||
nor_g: Normal,
|
|
||||||
wavelength: f32,
|
|
||||||
) -> SpectralSample;
|
|
||||||
|
|
||||||
/// Returns the pdf for the given 'in' direction producing the given 'out'
|
/// Returns the pdf for the given 'in' direction producing the given 'out'
|
||||||
/// direction with the given differential geometry.
|
/// direction with the given differential geometry.
|
||||||
|
@ -174,12 +169,16 @@ fn schlick_fresnel_from_fac(frensel_fac: f32, c: f32) -> f32 {
|
||||||
/// behave like a standard closure!
|
/// behave like a standard closure!
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct EmitClosure {
|
pub struct EmitClosure {
|
||||||
col: XYZ,
|
col: SpectralSample,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmitClosure {
|
impl EmitClosure {
|
||||||
pub fn emitted_color(&self, wavelength: f32) -> SpectralSample {
|
pub fn new(color: SpectralSample) -> EmitClosure {
|
||||||
self.col.to_spectral_sample(wavelength)
|
EmitClosure { col: color }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emitted_color(&self) -> SpectralSample {
|
||||||
|
self.col
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,28 +193,16 @@ impl SurfaceClosure for EmitClosure {
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
nor_g: Normal,
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
let _ = (inc, nor, nor_g, uv); // Not using these, silence warning
|
let _ = (inc, nor, nor_g, uv); // Not using these, silence warning
|
||||||
|
|
||||||
(
|
(Vector::new(0.0, 0.0, 0.0), self.col, 1.0)
|
||||||
Vector::new(0.0, 0.0, 0.0),
|
|
||||||
SpectralSample::new(wavelength),
|
|
||||||
1.0,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> SpectralSample {
|
||||||
&self,
|
|
||||||
inc: Vector,
|
|
||||||
out: Vector,
|
|
||||||
nor: Normal,
|
|
||||||
nor_g: Normal,
|
|
||||||
wavelength: f32,
|
|
||||||
) -> SpectralSample {
|
|
||||||
let _ = (inc, out, nor, nor_g); // Not using these, silence warning
|
let _ = (inc, out, nor, nor_g); // Not using these, silence warning
|
||||||
|
|
||||||
SpectralSample::new(wavelength)
|
self.col
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32 {
|
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32 {
|
||||||
|
@ -243,11 +230,11 @@ impl SurfaceClosure for EmitClosure {
|
||||||
/// Lambertian surface closure
|
/// Lambertian surface closure
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct LambertClosure {
|
pub struct LambertClosure {
|
||||||
col: XYZ,
|
col: SpectralSample,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LambertClosure {
|
impl LambertClosure {
|
||||||
pub fn new(col: XYZ) -> LambertClosure {
|
pub fn new(col: SpectralSample) -> LambertClosure {
|
||||||
LambertClosure { col: col }
|
LambertClosure { col: col }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +250,6 @@ impl SurfaceClosure for LambertClosure {
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
nor_g: Normal,
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
(nor.normalized().into_vector(), nor_g.into_vector())
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
|
@ -279,21 +265,14 @@ impl SurfaceClosure for LambertClosure {
|
||||||
|
|
||||||
// Make sure it's not on the wrong side of the geometric normal.
|
// Make sure it's not on the wrong side of the geometric normal.
|
||||||
if dot(flipped_nor_g, out) >= 0.0 {
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
let filter = self.evaluate(inc, out, nor, nor_g, wavelength);
|
let filter = self.evaluate(inc, out, nor, nor_g);
|
||||||
(out, filter, pdf)
|
(out, filter, pdf)
|
||||||
} else {
|
} else {
|
||||||
(out, SpectralSample::from_value(0.0, 0.0), 0.0)
|
(out, SpectralSample::new(0.0), 0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> SpectralSample {
|
||||||
&self,
|
|
||||||
inc: Vector,
|
|
||||||
out: Vector,
|
|
||||||
nor: Normal,
|
|
||||||
nor_g: Normal,
|
|
||||||
wavelength: f32,
|
|
||||||
) -> SpectralSample {
|
|
||||||
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
(nor.normalized().into_vector(), nor_g.into_vector())
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
} else {
|
} else {
|
||||||
|
@ -302,9 +281,9 @@ impl SurfaceClosure for LambertClosure {
|
||||||
|
|
||||||
if dot(flipped_nor_g, out) >= 0.0 {
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
let fac = dot(nn, out.normalized()).max(0.0) * INV_PI;
|
let fac = dot(nn, out.normalized()).max(0.0) * INV_PI;
|
||||||
self.col.to_spectral_sample(wavelength) * fac
|
self.col * fac
|
||||||
} else {
|
} else {
|
||||||
SpectralSample::from_value(0.0, 0.0)
|
SpectralSample::new(0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +368,7 @@ impl SurfaceClosure for LambertClosure {
|
||||||
/// The GTR microfacet BRDF from the Disney Principled BRDF paper.
|
/// The GTR microfacet BRDF from the Disney Principled BRDF paper.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct GTRClosure {
|
pub struct GTRClosure {
|
||||||
col: XYZ,
|
col: SpectralSample,
|
||||||
roughness: f32,
|
roughness: f32,
|
||||||
tail_shape: f32,
|
tail_shape: f32,
|
||||||
fresnel: f32, // [0.0, 1.0] determines how much fresnel reflection comes into play
|
fresnel: f32, // [0.0, 1.0] determines how much fresnel reflection comes into play
|
||||||
|
@ -397,7 +376,7 @@ pub struct GTRClosure {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GTRClosure {
|
impl GTRClosure {
|
||||||
pub fn new(col: XYZ, roughness: f32, tail_shape: f32, fresnel: f32) -> GTRClosure {
|
pub fn new(col: SpectralSample, roughness: f32, tail_shape: f32, fresnel: f32) -> GTRClosure {
|
||||||
let mut closure = GTRClosure {
|
let mut closure = GTRClosure {
|
||||||
col: col,
|
col: col,
|
||||||
roughness: roughness,
|
roughness: roughness,
|
||||||
|
@ -494,7 +473,6 @@ impl SurfaceClosure for GTRClosure {
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
nor_g: Normal,
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
// Get normalized surface normal
|
// Get normalized surface normal
|
||||||
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
|
@ -515,23 +493,16 @@ impl SurfaceClosure for GTRClosure {
|
||||||
|
|
||||||
// Make sure it's not on the wrong side of the geometric normal.
|
// Make sure it's not on the wrong side of the geometric normal.
|
||||||
if dot(flipped_nor_g, out) >= 0.0 {
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
let filter = self.evaluate(inc, out, nor, nor_g, wavelength);
|
let filter = self.evaluate(inc, out, nor, nor_g);
|
||||||
let pdf = self.sample_pdf(inc, out, nor, nor_g);
|
let pdf = self.sample_pdf(inc, out, nor, nor_g);
|
||||||
(out, filter, pdf)
|
(out, filter, pdf)
|
||||||
} else {
|
} else {
|
||||||
(out, SpectralSample::from_value(0.0, 0.0), 0.0)
|
(out, SpectralSample::new(0.0), 0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> SpectralSample {
|
||||||
&self,
|
|
||||||
inc: Vector,
|
|
||||||
out: Vector,
|
|
||||||
nor: Normal,
|
|
||||||
nor_g: Normal,
|
|
||||||
wavelength: f32,
|
|
||||||
) -> SpectralSample {
|
|
||||||
// Calculate needed vectors, normalized
|
// Calculate needed vectors, normalized
|
||||||
let aa = -inc.normalized(); // Vector pointing to where "in" came from
|
let aa = -inc.normalized(); // Vector pointing to where "in" came from
|
||||||
let bb = out.normalized(); // Out
|
let bb = out.normalized(); // Out
|
||||||
|
@ -546,7 +517,7 @@ impl SurfaceClosure for GTRClosure {
|
||||||
|
|
||||||
// Make sure everything's on the correct side of the surface
|
// Make sure everything's on the correct side of the surface
|
||||||
if dot(nn, aa) < 0.0 || dot(nn, bb) < 0.0 || dot(flipped_nor_g, bb) < 0.0 {
|
if dot(nn, aa) < 0.0 || dot(nn, bb) < 0.0 || dot(flipped_nor_g, bb) < 0.0 {
|
||||||
return SpectralSample::from_value(0.0, 0.0);
|
return SpectralSample::new(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate needed dot products
|
// Calculate needed dot products
|
||||||
|
@ -561,30 +532,29 @@ impl SurfaceClosure for GTRClosure {
|
||||||
|
|
||||||
// Calculate F - Fresnel
|
// Calculate F - Fresnel
|
||||||
let col_f = {
|
let col_f = {
|
||||||
let mut col_f = self.col.to_spectral_sample(wavelength);
|
|
||||||
|
|
||||||
let rev_fresnel = 1.0 - self.fresnel;
|
let rev_fresnel = 1.0 - self.fresnel;
|
||||||
let c0 = lerp(
|
let c0 = lerp(
|
||||||
schlick_fresnel_from_fac(col_f.e.get_0(), hb),
|
schlick_fresnel_from_fac(self.col.e.get_0(), hb),
|
||||||
col_f.e.get_0(),
|
self.col.e.get_0(),
|
||||||
rev_fresnel,
|
rev_fresnel,
|
||||||
);
|
);
|
||||||
let c1 = lerp(
|
let c1 = lerp(
|
||||||
schlick_fresnel_from_fac(col_f.e.get_1(), hb),
|
schlick_fresnel_from_fac(self.col.e.get_1(), hb),
|
||||||
col_f.e.get_1(),
|
self.col.e.get_1(),
|
||||||
rev_fresnel,
|
rev_fresnel,
|
||||||
);
|
);
|
||||||
let c2 = lerp(
|
let c2 = lerp(
|
||||||
schlick_fresnel_from_fac(col_f.e.get_2(), hb),
|
schlick_fresnel_from_fac(self.col.e.get_2(), hb),
|
||||||
col_f.e.get_2(),
|
self.col.e.get_2(),
|
||||||
rev_fresnel,
|
rev_fresnel,
|
||||||
);
|
);
|
||||||
let c3 = lerp(
|
let c3 = lerp(
|
||||||
schlick_fresnel_from_fac(col_f.e.get_3(), hb),
|
schlick_fresnel_from_fac(self.col.e.get_3(), hb),
|
||||||
col_f.e.get_3(),
|
self.col.e.get_3(),
|
||||||
rev_fresnel,
|
rev_fresnel,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut col_f = self.col;
|
||||||
col_f.e.set_0(c0);
|
col_f.e.set_0(c0);
|
||||||
col_f.e.set_1(c1);
|
col_f.e.set_1(c1);
|
||||||
col_f.e.set_2(c2);
|
col_f.e.set_2(c2);
|
||||||
|
|
|
@ -10,7 +10,7 @@ use fp_utils::fp_gamma;
|
||||||
use lerp::lerp_slice;
|
use lerp::lerp_slice;
|
||||||
use math::{Point, Normal, Matrix4x4, dot, cross};
|
use math::{Point, Normal, Matrix4x4, dot, cross};
|
||||||
use ray::{Ray, AccelRay};
|
use ray::{Ray, AccelRay};
|
||||||
use shading::surface_closure::{SurfaceClosureUnion, GTRClosure, LambertClosure};
|
use shading::{SurfaceShader, SimpleSurfaceShader};
|
||||||
|
|
||||||
use super::{Surface, SurfaceIntersection, SurfaceIntersectionData};
|
use super::{Surface, SurfaceIntersection, SurfaceIntersectionData};
|
||||||
use super::triangle;
|
use super::triangle;
|
||||||
|
@ -235,9 +235,7 @@ impl<'a> Surface for TriangleMesh<'a> {
|
||||||
geo_normal
|
geo_normal
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fill in intersection data
|
let intersection_data = SurfaceIntersectionData {
|
||||||
isects[r.id as usize] = SurfaceIntersection::Hit {
|
|
||||||
intersection_data: SurfaceIntersectionData {
|
|
||||||
incoming: wr.dir,
|
incoming: wr.dir,
|
||||||
t: t,
|
t: t,
|
||||||
pos: pos,
|
pos: pos,
|
||||||
|
@ -246,17 +244,21 @@ impl<'a> Surface for TriangleMesh<'a> {
|
||||||
nor_g: geo_normal,
|
nor_g: geo_normal,
|
||||||
uv: (0.0, 0.0), // TODO
|
uv: (0.0, 0.0), // TODO
|
||||||
local_space: mat_space,
|
local_space: mat_space,
|
||||||
},
|
};
|
||||||
// TODO: get surface closure from surface shader.
|
|
||||||
closure: SurfaceClosureUnion::LambertClosure(
|
// Fill in intersection data
|
||||||
LambertClosure::new(XYZ::new(0.8, 0.8, 0.8)),
|
isects[r.id as usize] = SurfaceIntersection::Hit {
|
||||||
),
|
intersection_data: intersection_data,
|
||||||
// closure:
|
// TODO: get surface shader from user-defined shader.
|
||||||
// SurfaceClosureUnion::GTRClosure(
|
closure: SimpleSurfaceShader::Lambert {
|
||||||
// GTRClosure::new(XYZ::new(0.8, 0.8, 0.8),
|
color: XYZ::new(0.8, 0.8, 0.8),
|
||||||
// 0.1,
|
}.shade(&intersection_data, wr.wavelength),
|
||||||
// 2.0,
|
// closure: SimpleSurfaceShader::GTR {
|
||||||
// 1.0)),
|
// color: XYZ::new(0.8, 0.8, 0.8),
|
||||||
|
// roughness: 0.1,
|
||||||
|
// tail_shape: 2.0,
|
||||||
|
// fresnel: 1.0,
|
||||||
|
// }.shade(&intersection_data, wr.wavelength),
|
||||||
};
|
};
|
||||||
r.max_t = t;
|
r.max_t = t;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user