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 /intern | |
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.
Diffstat (limited to 'intern')
-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; |