diff options
author | Lukas Stockner <lukas.stockner@freenet.de> | 2022-04-30 14:49:45 +0300 |
---|---|---|
committer | Lukas Stockner <lukas.stockner@freenet.de> | 2022-04-30 14:49:45 +0300 |
commit | ac88123e29d4e07101a4fb33de28429d5e033367 (patch) | |
tree | 94608219d46a0194bd42a1cb5dabee4cb3bc1ce7 | |
parent | 5c92c04518b5dc7c57c3b3a9e81b45879af2e080 (diff) |
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.
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_microfacet_multi.h | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index c646c9ef01d..10027ae9f77 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -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; |