Surface closures and light sampling now take both shading and geometric normals.
This will allow them to appropriately handle weirdness that comes from the shading normal and geometric normal being different.
This commit is contained in:
parent
05578a1240
commit
0481d931b9
|
@ -45,11 +45,12 @@ impl<'a> LightAccel for LightArray<'a> {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
sc: &SurfaceClosure,
|
sc: &SurfaceClosure,
|
||||||
time: f32,
|
time: f32,
|
||||||
n: f32,
|
n: f32,
|
||||||
) -> Option<(usize, f32, f32)> {
|
) -> Option<(usize, f32, f32)> {
|
||||||
let _ = (inc, pos, nor, sc, time); // Not using these, silence warnings
|
let _ = (inc, pos, nor, nor_g, sc, time); // Not using these, silence warnings
|
||||||
|
|
||||||
assert!(n >= 0.0 && n <= 1.0);
|
assert!(n >= 0.0 && n <= 1.0);
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ impl<'a> LightAccel for LightTree<'a> {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
sc: &SurfaceClosure,
|
sc: &SurfaceClosure,
|
||||||
time: f32,
|
time: f32,
|
||||||
n: f32,
|
n: f32,
|
||||||
|
@ -160,7 +161,7 @@ impl<'a> LightAccel for LightTree<'a> {
|
||||||
let sin_theta_max2 = (r2 / dist2).min(1.0);
|
let sin_theta_max2 = (r2 / dist2).min(1.0);
|
||||||
(1.0 - sin_theta_max2).sqrt()
|
(1.0 - sin_theta_max2).sqrt()
|
||||||
};
|
};
|
||||||
sc.estimate_eval_over_solid_angle(inc, d, nor, cos_theta_max)
|
sc.estimate_eval_over_solid_angle(inc, d, nor, nor_g, cos_theta_max)
|
||||||
};
|
};
|
||||||
|
|
||||||
node_ref.energy() * inv_surface_area * approx_contrib
|
node_ref.energy() * inv_surface_area * approx_contrib
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub trait LightAccel {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
sc: &SurfaceClosure,
|
sc: &SurfaceClosure,
|
||||||
time: f32,
|
time: f32,
|
||||||
n: f32,
|
n: f32,
|
||||||
|
|
|
@ -467,36 +467,41 @@ 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 {
|
||||||
// Calculate and store the light that will be contributed
|
let material = closure.as_surface_closure();
|
||||||
// to the film plane if the light is not in shadow.
|
let attenuation = material.evaluate(
|
||||||
self.pending_color_addition = {
|
ray.dir,
|
||||||
let material = closure.as_surface_closure();
|
|
||||||
let la = material.evaluate(
|
|
||||||
ray.dir,
|
|
||||||
shadow_vec,
|
|
||||||
idata.nor,
|
|
||||||
self.wavelength,
|
|
||||||
);
|
|
||||||
light_color.e * la.e * self.light_attenuation /
|
|
||||||
(light_pdf * light_sel_pdf)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate the shadow ray for testing if the light is
|
|
||||||
// in shadow or not.
|
|
||||||
let offset_pos = robust_ray_origin(
|
|
||||||
idata.pos,
|
|
||||||
idata.pos_err,
|
|
||||||
idata.nor_g.normalized(),
|
|
||||||
shadow_vec,
|
shadow_vec,
|
||||||
|
idata.nor,
|
||||||
|
idata.nor_g,
|
||||||
|
self.wavelength,
|
||||||
);
|
);
|
||||||
*ray = Ray::new(offset_pos, shadow_vec, self.time, true);
|
|
||||||
|
|
||||||
// For distant lights
|
if attenuation.e.h_max() > 0.0 {
|
||||||
if is_infinite {
|
// Calculate and store the light that will be contributed
|
||||||
ray.max_t = std::f32::INFINITY;
|
// to the film plane if the light is not in shadow.
|
||||||
|
self.pending_color_addition = light_color.e * attenuation.e *
|
||||||
|
self.light_attenuation /
|
||||||
|
(light_pdf * light_sel_pdf);
|
||||||
|
|
||||||
|
// Calculate the shadow ray for testing if the light is
|
||||||
|
// in shadow or not.
|
||||||
|
let offset_pos = robust_ray_origin(
|
||||||
|
idata.pos,
|
||||||
|
idata.pos_err,
|
||||||
|
idata.nor_g.normalized(),
|
||||||
|
shadow_vec,
|
||||||
|
);
|
||||||
|
*ray = Ray::new(offset_pos, shadow_vec, self.time, true);
|
||||||
|
|
||||||
|
// For distant lights
|
||||||
|
if is_infinite {
|
||||||
|
ray.max_t = std::f32::INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -513,11 +518,17 @@ 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(idata.incoming, idata.nor, (u, v), self.wavelength)
|
material.sample(
|
||||||
|
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.
|
||||||
if pdf > 0.0 {
|
if (pdf > 0.0) && (filter.e.h_max() > 0.0) {
|
||||||
// Account for the additional light attenuation from
|
// Account for the additional light attenuation from
|
||||||
// this bounce
|
// this bounce
|
||||||
self.next_attentuation_fac = filter.e / pdf;
|
self.next_attentuation_fac = filter.e / pdf;
|
||||||
|
|
|
@ -60,6 +60,7 @@ impl<'a> Assembly<'a> {
|
||||||
idata.incoming * sel_xform,
|
idata.incoming * sel_xform,
|
||||||
idata.pos * sel_xform,
|
idata.pos * sel_xform,
|
||||||
idata.nor * sel_xform,
|
idata.nor * sel_xform,
|
||||||
|
idata.nor_g * sel_xform,
|
||||||
closure.as_surface_closure(),
|
closure.as_surface_closure(),
|
||||||
time,
|
time,
|
||||||
n,
|
n,
|
||||||
|
|
|
@ -36,9 +36,10 @@ pub trait SurfaceClosure {
|
||||||
/// Given an incoming ray and sample values, generates an outgoing ray and
|
/// Given an incoming ray and sample values, generates an outgoing ray and
|
||||||
/// color filter.
|
/// color filter.
|
||||||
///
|
///
|
||||||
/// inc: Incoming light direction.
|
/// inc: Incoming light direction.
|
||||||
/// nor: The surface normal at the surface point.
|
/// nor: The shading surface normal at the surface point.
|
||||||
/// uv: The sampling values.
|
/// nor_g: The geometric surface normal at the surface point.
|
||||||
|
/// uv: The sampling values.
|
||||||
/// wavelength: The wavelength of light to sample at.
|
/// 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.
|
||||||
|
@ -46,27 +47,37 @@ pub trait SurfaceClosure {
|
||||||
&self,
|
&self,
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: 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.
|
||||||
///
|
///
|
||||||
/// inc: The incoming light direction.
|
/// inc: The incoming light direction.
|
||||||
/// out: The outgoing light direction.
|
/// out: The outgoing light direction.
|
||||||
/// nor: The surface normal of the reflecting/transmitting surface point.
|
/// nor: The shading surface normal at the surface point.
|
||||||
|
/// nor_g: The geometric surface normal at the surface point.
|
||||||
/// 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(&self, inc: Vector, out: Vector, nor: Normal, wavelength: f32) -> SpectralSample;
|
fn evaluate(
|
||||||
|
&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.
|
||||||
///
|
///
|
||||||
/// inc: The incoming light direction.
|
/// inc: The incoming light direction.
|
||||||
/// out: The outgoing light direction.
|
/// out: The outgoing light direction.
|
||||||
/// nor: The surface normal of the reflecting/transmitting surface point.
|
/// nor: The shading surface normal at the surface point.
|
||||||
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal) -> f32;
|
/// nor_g: The geometric surface normal at the surface point.
|
||||||
|
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32;
|
||||||
|
|
||||||
/// Returns an estimate of the sum total energy that evaluate() would return
|
/// Returns an estimate of the sum total energy that evaluate() would return
|
||||||
/// when 'out' is evaluated over a circular solid angle.
|
/// when 'out' is evaluated over a circular solid angle.
|
||||||
|
@ -78,6 +89,7 @@ pub trait SurfaceClosure {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
out: Vector,
|
out: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
cos_theta: f32,
|
cos_theta: f32,
|
||||||
) -> f32;
|
) -> f32;
|
||||||
}
|
}
|
||||||
|
@ -180,10 +192,11 @@ impl SurfaceClosure for EmitClosure {
|
||||||
&self,
|
&self,
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
let _ = (inc, nor, 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),
|
Vector::new(0.0, 0.0, 0.0),
|
||||||
|
@ -192,14 +205,21 @@ impl SurfaceClosure for EmitClosure {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, wavelength: f32) -> SpectralSample {
|
fn evaluate(
|
||||||
let _ = (inc, out, nor); // Not using these, silence warning
|
&self,
|
||||||
|
inc: Vector,
|
||||||
|
out: Vector,
|
||||||
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
|
wavelength: f32,
|
||||||
|
) -> SpectralSample {
|
||||||
|
let _ = (inc, out, nor, nor_g); // Not using these, silence warning
|
||||||
|
|
||||||
SpectralSample::new(wavelength)
|
SpectralSample::new(wavelength)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal) -> f32 {
|
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32 {
|
||||||
let _ = (inc, out, nor); // Not using these, silence warning
|
let _ = (inc, out, nor, nor_g); // Not using these, silence warning
|
||||||
|
|
||||||
1.0
|
1.0
|
||||||
}
|
}
|
||||||
|
@ -209,9 +229,10 @@ impl SurfaceClosure for EmitClosure {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
out: Vector,
|
out: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
cos_theta: f32,
|
cos_theta: f32,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
let _ = (inc, out, nor, cos_theta); // Not using these, silence warning
|
let _ = (inc, out, nor, nor_g, cos_theta); // Not using these, silence warning
|
||||||
|
|
||||||
// TODO: what to do here?
|
// TODO: what to do here?
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
@ -240,10 +261,11 @@ impl SurfaceClosure for LambertClosure {
|
||||||
&self,
|
&self,
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
let nn = if dot(nor.into_vector(), inc) <= 0.0 {
|
let nn = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
nor.normalized()
|
nor.normalized()
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized()
|
-nor.normalized()
|
||||||
|
@ -254,14 +276,21 @@ impl SurfaceClosure for LambertClosure {
|
||||||
let dir = cosine_sample_hemisphere(uv.0, uv.1);
|
let dir = cosine_sample_hemisphere(uv.0, uv.1);
|
||||||
let pdf = dir.z() * INV_PI;
|
let pdf = dir.z() * INV_PI;
|
||||||
let out = zup_to_vec(dir, nn);
|
let out = zup_to_vec(dir, nn);
|
||||||
let filter = self.evaluate(inc, out, nor, wavelength);
|
let filter = self.evaluate(inc, out, nor, nor_g, wavelength);
|
||||||
|
|
||||||
(out, filter, pdf)
|
(out, filter, pdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, wavelength: f32) -> SpectralSample {
|
fn evaluate(
|
||||||
|
&self,
|
||||||
|
inc: Vector,
|
||||||
|
out: Vector,
|
||||||
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
|
wavelength: f32,
|
||||||
|
) -> SpectralSample {
|
||||||
let v = out.normalized();
|
let v = out.normalized();
|
||||||
let nn = if dot(nor.into_vector(), inc) <= 0.0 {
|
let nn = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
nor.normalized()
|
nor.normalized()
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized()
|
-nor.normalized()
|
||||||
|
@ -271,9 +300,9 @@ impl SurfaceClosure for LambertClosure {
|
||||||
self.col.to_spectral_sample(wavelength) * fac
|
self.col.to_spectral_sample(wavelength) * fac
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal) -> f32 {
|
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32 {
|
||||||
let v = out.normalized();
|
let v = out.normalized();
|
||||||
let nn = if dot(nor.into_vector(), inc) <= 0.0 {
|
let nn = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
nor.normalized()
|
nor.normalized()
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized()
|
-nor.normalized()
|
||||||
|
@ -287,8 +316,11 @@ impl SurfaceClosure for LambertClosure {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
out: Vector,
|
out: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
cos_theta: f32,
|
cos_theta: f32,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
|
let _ = nor_g; // Not using this, silence warning
|
||||||
|
|
||||||
assert!(cos_theta >= -1.0 && cos_theta <= 1.0);
|
assert!(cos_theta >= -1.0 && cos_theta <= 1.0);
|
||||||
|
|
||||||
// Analytically calculates lambert shading from a uniform light source
|
// Analytically calculates lambert shading from a uniform light source
|
||||||
|
@ -449,11 +481,12 @@ impl SurfaceClosure for GTRClosure {
|
||||||
&self,
|
&self,
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
// Get normalized surface normal
|
// Get normalized surface normal
|
||||||
let nn = if dot(nor.into_vector(), inc) < 0.0 {
|
let nn = if dot(nor_g.into_vector(), inc) < 0.0 {
|
||||||
nor.normalized()
|
nor.normalized()
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized() // If back-facing, flip normal
|
-nor.normalized() // If back-facing, flip normal
|
||||||
|
@ -468,26 +501,37 @@ impl SurfaceClosure for GTRClosure {
|
||||||
half_dir = zup_to_vec(half_dir, nn).normalized();
|
half_dir = zup_to_vec(half_dir, nn).normalized();
|
||||||
|
|
||||||
let out = inc - (half_dir * 2.0 * dot(inc, half_dir));
|
let out = inc - (half_dir * 2.0 * dot(inc, half_dir));
|
||||||
let filter = self.evaluate(inc, out, nor, wavelength);
|
let filter = self.evaluate(inc, out, nor, nor_g, wavelength);
|
||||||
let pdf = self.sample_pdf(inc, out, nor);
|
let pdf = self.sample_pdf(inc, out, nor, nor_g);
|
||||||
|
|
||||||
(out, filter, pdf)
|
(out, filter, pdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, wavelength: f32) -> SpectralSample {
|
fn evaluate(
|
||||||
|
&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
|
||||||
let hh = (aa + bb).normalized(); // Half-way between aa and bb
|
let hh = (aa + bb).normalized(); // Half-way between aa and bb
|
||||||
|
|
||||||
// Surface normal
|
// Surface normal
|
||||||
let nn = if dot(nor.into_vector(), hh) < 0.0 {
|
let nn = if dot(nor_g.into_vector(), hh) < 0.0 {
|
||||||
-nor.normalized() // If back-facing, flip normal
|
-nor.normalized() // If back-facing, flip normal
|
||||||
} else {
|
} else {
|
||||||
nor.normalized()
|
nor.normalized()
|
||||||
}.into_vector();
|
}.into_vector();
|
||||||
|
|
||||||
|
if dot(nn, aa) < 0.0 {
|
||||||
|
return SpectralSample::from_value(0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate needed dot products
|
// Calculate needed dot products
|
||||||
let na = clamp(dot(nn, aa), -1.0, 1.0);
|
let na = clamp(dot(nn, aa), -1.0, 1.0);
|
||||||
let nb = clamp(dot(nn, bb), -1.0, 1.0);
|
let nb = clamp(dot(nn, bb), -1.0, 1.0);
|
||||||
|
@ -571,19 +615,23 @@ impl SurfaceClosure for GTRClosure {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal) -> f32 {
|
fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32 {
|
||||||
// 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
|
||||||
let hh = (aa + bb).normalized(); // Half-way between aa and bb
|
let hh = (aa + bb).normalized(); // Half-way between aa and bb
|
||||||
|
|
||||||
// Surface normal
|
// Surface normal
|
||||||
let nn = if dot(nor.into_vector(), hh) < 0.0 {
|
let nn = if dot(nor_g.into_vector(), hh) < 0.0 {
|
||||||
-nor.normalized() // If back-facing, flip normal
|
-nor.normalized() // If back-facing, flip normal
|
||||||
} else {
|
} else {
|
||||||
nor.normalized()
|
nor.normalized()
|
||||||
}.into_vector();
|
}.into_vector();
|
||||||
|
|
||||||
|
if dot(nn, aa) < 0.0 {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate needed dot products
|
// Calculate needed dot products
|
||||||
let nh = clamp(dot(nn, hh), -1.0, 1.0);
|
let nh = clamp(dot(nn, hh), -1.0, 1.0);
|
||||||
|
|
||||||
|
@ -596,11 +644,15 @@ impl SurfaceClosure for GTRClosure {
|
||||||
inc: Vector,
|
inc: Vector,
|
||||||
out: Vector,
|
out: Vector,
|
||||||
nor: Normal,
|
nor: Normal,
|
||||||
|
nor_g: Normal,
|
||||||
cos_theta: f32,
|
cos_theta: f32,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
// TODO: all of the stuff in this function is horribly hacky.
|
// TODO: all of the stuff in this function is horribly hacky.
|
||||||
// Find a proper way to approximate the light contribution from a
|
// Find a proper way to approximate the light contribution from a
|
||||||
// solid angle.
|
// solid angle.
|
||||||
|
|
||||||
|
let _ = nor_g; // Not using this, silence warning
|
||||||
|
|
||||||
assert!(cos_theta >= -1.0);
|
assert!(cos_theta >= -1.0);
|
||||||
assert!(cos_theta <= 1.0);
|
assert!(cos_theta <= 1.0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user