diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 5cb4ab26ed6..7041c5deb6c 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -532,15 +532,18 @@ ccl_device_inline case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID: - eval = bsdf_microfacet_ggx_eval(kg, sc, sd->wi, wo, pdf); + /* For consistency with eval() this should be using sd->Ng, but that causes + * artifacts (see shadow_terminator_metal test). Needs deeper investigation + * for how to solve this. */ + eval = bsdf_microfacet_ggx_eval(kg, sc, sd->N, sd->wi, wo, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: - eval = bsdf_microfacet_beckmann_eval(kg, sc, sd->wi, wo, pdf); + eval = bsdf_microfacet_beckmann_eval(kg, sc, sd->N, sd->wi, wo, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: - eval = bsdf_ashikhmin_shirley_eval(sc, sd->wi, wo, pdf); + eval = bsdf_ashikhmin_shirley_eval(sc, sd->N, sd->wi, wo, pdf); break; case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: eval = bsdf_ashikhmin_velvet_eval(sc, sd->wi, wo, pdf); diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index d14f0290a90..67b601c87d8 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -46,11 +46,13 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(const float } ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(const ccl_private ShaderClosure *sc, + const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf) { const ccl_private MicrofacetBsdf *bsdf = (const ccl_private MicrofacetBsdf *)sc; + const float cosNgO = dot(Ng, wo); const float3 N = bsdf->N; float NdotI = dot(N, wi); @@ -58,7 +60,9 @@ ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(const ccl_private Sh float out = 0.0f; - if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f || (NdotI < 0.0f) || (NdotO < 0.0f)) { + if ((cosNgO < 0.0f) || fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f || + !(NdotI > 0.0f && NdotO > 0.0f)) + { *pdf = 0.0f; return zero_spectrum(); } @@ -204,13 +208,6 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ccl_private ShaderClosure *sc /* reflect wi on H to get wo */ *wo = -wi + (2.0f * HdotI) * H; - /* Check hemisphere. */ - if (dot(Ng, *wo) < 0.0f) { - *pdf = 0.0f; - *eval = zero_spectrum(); - return LABEL_NONE; - } - if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) { /* Some high number for MIS. */ *pdf = 1e6f; @@ -219,7 +216,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ccl_private ShaderClosure *sc } else { /* leave the rest to eval */ - *eval = bsdf_ashikhmin_shirley_eval(sc, wi, *wo, pdf); + *eval = bsdf_ashikhmin_shirley_eval(sc, Ng, wi, *wo, pdf); } return label; diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 35bb4c17d5e..22eaa5df1c5 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -564,6 +564,7 @@ ccl_device_forceinline int bsdf_microfacet_eval_flag(const ccl_private Microface template ccl_device Spectrum bsdf_microfacet_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, + const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf) @@ -577,6 +578,7 @@ ccl_device Spectrum bsdf_microfacet_eval(KernelGlobals kg, const float3 N = bsdf->N; const float cos_NI = dot(N, wi); const float cos_NO = dot(N, wo); + const float cos_NgO = dot(Ng, wo); const float alpha_x = bsdf->alpha_x; const float alpha_y = bsdf->alpha_y; @@ -586,10 +588,11 @@ ccl_device Spectrum bsdf_microfacet_eval(KernelGlobals kg, /* Check whether the pair of directions is valid for evaluation: * - Incoming direction has to be in the upper hemisphere (Cycles convention) * - Specular cases can't be evaluated, only sampled. + * - The outgoing direction has to be the in the same hemisphere w.r.t. both normals. * - Purely reflective closures can't have refraction. * - Purely refractive closures can't have reflection. */ - if ((cos_NI <= 0) || !bsdf_microfacet_eval_flag(bsdf) || + if ((cos_NI <= 0) || !bsdf_microfacet_eval_flag(bsdf) || ((cos_NgO < 0.0f) != is_transmission) || (is_transmission && !has_transmission) || (!is_transmission && !has_reflection)) { return zero_spectrum(); @@ -729,16 +732,7 @@ ccl_device int bsdf_microfacet_sample(KernelGlobals kg, /* Compute actual reflected or refracted direction. */ *wo = do_refract ? refract_angle(wi, H, cos_HO, m_inv_eta) : 2.0f * cos_HI * H - wi; - - /* Ensure that the sampled direction lies in the correct hemisphere. - * Note that the check against Ng is only performed in the sampling code, not the evaluation. - * This is technically inconsistent, but required in order to avoid shadow terminator artifacts - * on smooth geometry (which we'd get if we checked Ng in evaluation) while ensuring that - * sampling doesn't return supposed reflection rays going into the geometry and vice versa. - * The same is done for other closures as well. */ - const float cos_NO = dot(N, *wo); - const float cos_NgO = dot(Ng, *wo); - if ((cos_NgO < 0) != do_refract || (cos_NO < 0) != do_refract) { + if ((dot(Ng, *wo) < 0) != do_refract) { return LABEL_NONE; } @@ -982,12 +976,13 @@ ccl_device void bsdf_microfacet_blur(ccl_private ShaderClosure *sc, const float ccl_device Spectrum bsdf_microfacet_ggx_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, + const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf) { const ccl_private MicrofacetBsdf *bsdf = (const ccl_private MicrofacetBsdf *)sc; - return bsdf->energy_scale * bsdf_microfacet_eval(kg, sc, wi, wo, pdf); + return bsdf->energy_scale * bsdf_microfacet_eval(kg, sc, Ng, wi, wo, pdf); } ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, @@ -1048,11 +1043,12 @@ ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf * ccl_device Spectrum bsdf_microfacet_beckmann_eval(KernelGlobals kg, const ccl_private ShaderClosure *sc, + const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf) { - return bsdf_microfacet_eval(kg, sc, wi, wo, pdf); + return bsdf_microfacet_eval(kg, sc, Ng, wi, wo, pdf); } ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, diff --git a/intern/cycles/kernel/closure/bsdf_sheen.h b/intern/cycles/kernel/closure/bsdf_sheen.h index d06f5d5f1ef..bd0e1f0255b 100644 --- a/intern/cycles/kernel/closure/bsdf_sheen.h +++ b/intern/cycles/kernel/closure/bsdf_sheen.h @@ -65,10 +65,19 @@ ccl_device Spectrum bsdf_sheen_eval(const ccl_private ShaderClosure *sc, const float a = bsdf->transformA; const float b = bsdf->transformB; + if (dot(N, wo) <= 0.0f) { + *pdf = 0.0f; + return zero_spectrum(); + } + const float3 localO = to_local(wo, T, B, N); + if (localO.z <= 0.0f) { + *pdf = 0.0f; + return zero_spectrum(); + } const float lenSqr = sqr(a * localO.x + b * localO.z) + sqr(a * localO.y) + sqr(localO.z); - const float val = M_1_PI_F * fmaxf(localO.z, 0.0f) * sqr(a / lenSqr); + const float val = M_1_PI_F * localO.z * sqr(a / lenSqr); *pdf = val; return make_spectrum(val); diff --git a/tests/files/render/displacement/cycles_renders/bump_glass.png b/tests/files/render/displacement/cycles_renders/bump_glass.png index 636ed2edb40..e5f982330f6 100644 --- a/tests/files/render/displacement/cycles_renders/bump_glass.png +++ b/tests/files/render/displacement/cycles_renders/bump_glass.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c726a87c897164b4029c2b6cdba90b9a40210091f6063b9387eb5f37417cf8f -size 21859 +oid sha256:397b1d349142e56bfee49ae4771c1aed363e399653968c85240dcaab655db21b +size 21404 diff --git a/tests/files/render/displacement/cycles_renders/bump_glossy.png b/tests/files/render/displacement/cycles_renders/bump_glossy.png index 05b80f890ce..103e9a97f18 100644 --- a/tests/files/render/displacement/cycles_renders/bump_glossy.png +++ b/tests/files/render/displacement/cycles_renders/bump_glossy.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3460d9740346c932c7385ce9d27a03510dce3f1696d65c53db1249830969ff2a -size 19546 +oid sha256:db70ec4b7ba72c629723b49c9769e17f4b4fa9e04420687d081f879750caf4c7 +size 19189