Lambert and GTR now handle interpolated shading normals properly.
This commit is contained in:
parent
58a783b01e
commit
dd56a4e54b
|
@ -265,20 +265,25 @@ impl SurfaceClosure for LambertClosure {
|
||||||
uv: (f32, f32),
|
uv: (f32, f32),
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
let nn = 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()
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized()
|
(-nor.normalized().into_vector(), -nor_g.into_vector())
|
||||||
}.into_vector();
|
};
|
||||||
|
|
||||||
// Generate a random ray direction in the hemisphere
|
// Generate a random ray direction in the hemisphere
|
||||||
// of the surface.
|
// of the shading surface normal.
|
||||||
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, nor_g, wavelength);
|
|
||||||
|
|
||||||
(out, filter, pdf)
|
// Make sure it's not on the wrong side of the geometric normal.
|
||||||
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
|
let filter = self.evaluate(inc, out, nor, nor_g, wavelength);
|
||||||
|
(out, filter, pdf)
|
||||||
|
} else {
|
||||||
|
(out, SpectralSample::from_value(0.0, 0.0), 0.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
|
@ -289,26 +294,32 @@ impl SurfaceClosure for LambertClosure {
|
||||||
nor_g: Normal,
|
nor_g: Normal,
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
) -> SpectralSample {
|
) -> SpectralSample {
|
||||||
let v = out.normalized();
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
let nn = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
nor.normalized()
|
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized()
|
(-nor.normalized().into_vector(), -nor_g.into_vector())
|
||||||
}.into_vector();
|
};
|
||||||
let fac = dot(nn, v).max(0.0) * INV_PI;
|
|
||||||
|
|
||||||
self.col.to_spectral_sample(wavelength) * fac
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
|
let fac = dot(nn, out.normalized()).max(0.0) * INV_PI;
|
||||||
|
self.col.to_spectral_sample(wavelength) * fac
|
||||||
|
} else {
|
||||||
|
SpectralSample::from_value(0.0, 0.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
let v = out.normalized();
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
let nn = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
nor.normalized()
|
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized()
|
(-nor.normalized().into_vector(), -nor_g.into_vector())
|
||||||
}.into_vector();
|
};
|
||||||
|
|
||||||
dot(nn, v).max(0.0) * INV_PI
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
|
dot(nn, out.normalized()).max(0.0) * INV_PI
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_eval_over_solid_angle(
|
fn estimate_eval_over_solid_angle(
|
||||||
|
@ -361,7 +372,7 @@ impl SurfaceClosure for LambertClosure {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
} else {
|
} else {
|
||||||
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()
|
||||||
|
@ -486,11 +497,11 @@ impl SurfaceClosure for GTRClosure {
|
||||||
wavelength: f32,
|
wavelength: f32,
|
||||||
) -> (Vector, SpectralSample, f32) {
|
) -> (Vector, SpectralSample, f32) {
|
||||||
// Get normalized surface normal
|
// Get normalized surface normal
|
||||||
let nn = 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()
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
} else {
|
} else {
|
||||||
-nor.normalized() // If back-facing, flip normal
|
(-nor.normalized().into_vector(), -nor_g.into_vector())
|
||||||
}.into_vector();
|
};
|
||||||
|
|
||||||
// Generate a random ray direction in the hemisphere
|
// Generate a random ray direction in the hemisphere
|
||||||
// of the surface.
|
// of the surface.
|
||||||
|
@ -501,10 +512,15 @@ 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, nor_g, wavelength);
|
|
||||||
let pdf = self.sample_pdf(inc, out, nor, nor_g);
|
|
||||||
|
|
||||||
(out, filter, pdf)
|
// Make sure it's not on the wrong side of the geometric normal.
|
||||||
|
if dot(flipped_nor_g, out) >= 0.0 {
|
||||||
|
let filter = self.evaluate(inc, out, nor, nor_g, wavelength);
|
||||||
|
let pdf = self.sample_pdf(inc, out, nor, nor_g);
|
||||||
|
(out, filter, pdf)
|
||||||
|
} else {
|
||||||
|
(out, SpectralSample::from_value(0.0, 0.0), 0.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -522,13 +538,14 @@ impl SurfaceClosure for GTRClosure {
|
||||||
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_g.into_vector(), hh) < 0.0 {
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
-nor.normalized() // If back-facing, flip normal
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
} else {
|
} else {
|
||||||
nor.normalized()
|
(-nor.normalized().into_vector(), -nor_g.into_vector())
|
||||||
}.into_vector();
|
};
|
||||||
|
|
||||||
if dot(nn, aa) < 0.0 {
|
// 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 {
|
||||||
return SpectralSample::from_value(0.0, 0.0);
|
return SpectralSample::from_value(0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,13 +639,14 @@ impl SurfaceClosure for GTRClosure {
|
||||||
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_g.into_vector(), hh) < 0.0 {
|
let (nn, flipped_nor_g) = if dot(nor_g.into_vector(), inc) <= 0.0 {
|
||||||
-nor.normalized() // If back-facing, flip normal
|
(nor.normalized().into_vector(), nor_g.into_vector())
|
||||||
} else {
|
} else {
|
||||||
nor.normalized()
|
(-nor.normalized().into_vector(), -nor_g.into_vector())
|
||||||
}.into_vector();
|
};
|
||||||
|
|
||||||
if dot(nn, aa) < 0.0 {
|
// 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 {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user