Fix T96576: Light leaking when using normal maps with Multiscatter GGX

The Multiscatter GGX code was missing the same-side checks for incoming and
outgoing directions w.r.t. to shading and geometry normal.

Should not be needed for the Glass variant since it intentionally has both
reflection and transmission.
This commit is contained in:
Lukas Stockner 2022-04-30 13:49:45 +02:00
parent 5c92c04518
commit ac88123e29
Notes: blender-bot 2023-02-13 15:58:09 +01:00
Referenced by issue #96576, Regression: Light leaking when using normal maps with Multiscatter GGX
1 changed files with 29 additions and 4 deletions

View File

@ -438,11 +438,18 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const Shade
return make_float3(0.0f, 0.0f, 0.0f);
}
float3 X, Y, Z;
Z = bsdf->N;
/* Ensure that the both directions are on the outside w.r.t. the shading normal. */
if (dot(Z, I) <= 0.0f || dot(Z, omega_in) <= 0.0f) {
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
float3 X, Y, Z;
Z = bsdf->N;
if (is_aniso)
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
else
@ -487,8 +494,20 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
float3 X, Y, Z;
Z = bsdf->N;
/* Ensure that the view direction is on the outside w.r.t. the shading normal. */
if (dot(Z, I) <= 0.0f) {
*pdf = 0.0f;
return LABEL_NONE;
}
/* Special case: Extremely low roughness.
* Don't bother with microfacets, just do specular reflection. */
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
*omega_in = 2 * dot(Z, I) * Z - I;
if (dot(Ng, *omega_in) <= 0.0f) {
*pdf = 0.0f;
return LABEL_NONE;
}
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
#ifdef __RAY_DIFFERENTIALS__
@ -518,14 +537,20 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
bsdf->ior,
use_fresnel,
bsdf->extra->cspec0);
*omega_in = X * localO.x + Y * localO.y + Z * localO.z;
/* Ensure that the light direction is on the outside w.r.t. the geometry normal. */
if (dot(Ng, *omega_in) <= 0.0f) {
*pdf = 0.0f;
return LABEL_NONE;
}
if (is_aniso)
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
else
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
*eval *= *pdf;
*omega_in = X * localO.x + Y * localO.y + Z * localO.z;
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
*domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;