Commit: 73000c792d40e61df5e118b25757e37e6c6017b9 Author: Lukas Stockner Date: Tue Jan 24 03:53:32 2023 +0100 Branches: master https://developer.blender.org/rB73000c792d40e61df5e118b25757e37e6c6017b9
Cycles: Reorganize Fresnel handling in Microfacet closures This is both a cleanup and a preparation for the Principled v2 changes. Notable changes: - Clearcoat weight is now folded into the closure weight, there's no reason to track this separately. - There's a general-purpose helper for computing a Closure's albedo, which is currently used by the denoising albedo and diffuse/gloss/transmission color passes. - The d/g/t color passes didn't account for closure albedo before, this means that e.g. metallic shaders with Principled v2 now have their color texture included in the glossy color pass. Also fixes T104041 (sheen albedo). - Instead of precomputing and storing the albedo during shader setup, compute it when needed. This is technically redundant since we still need to compute it on shader setup to adjust the sample weight, but the operation is cheap enough that freeing up the storage seems worth it. - Future changes (Principled v2) are easier to integrate since the Fresnel handling isn't all over the place anymore. - Fresnel handling in the Multiscattering GGX code is still ugly, but since removing that entirely is the next step, putting effort into cleaning it up doesn't seem worth it. - Apart from the d/g/t color passes, no changes to render results are expected. Differential Revision: https://developer.blender.org/D17101 =================================================================== M intern/cycles/kernel/closure/bsdf.h M intern/cycles/kernel/closure/bsdf_microfacet.h M intern/cycles/kernel/closure/bsdf_microfacet_multi.h M intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h M intern/cycles/kernel/closure/bsdf_util.h M intern/cycles/kernel/film/denoising_passes.h M intern/cycles/kernel/integrator/surface_shader.h M intern/cycles/kernel/osl/closures_setup.h M intern/cycles/kernel/svm/closure.h M intern/cycles/kernel/svm/types.h =================================================================== diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index b0d01c427de..28829262ac9 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -661,4 +661,37 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float #endif } +ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd, ccl_private const ShaderClosure *sc) +{ + Spectrum albedo = sc->weight; + /* Some closures include additional components such as Fresnel terms that cause their albedo to + * be below 1. The point of this function is to return a best-effort estimation of their albedo, + * meaning the amount of reflected/refracted light that would be expected when illuminated by a + * uniform white background. + * This is used for the denoising albedo pass and diffuse/glossy/transmission color passes. + * NOTE: This should always match the sample_weight of the closure - as in, if there's an albedo + * adjustment in here, the sample_weight should also be reduced accordingly. + * TODO(lukas): Consider calling this function to determine the sample_weight? Would be a bit of + * extra overhead though. */ +#if defined(__SVM__) || defined(__OSL__) + switch (sc->type) { + case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: + albedo *= microfacet_fresnel((ccl_private const MicrofacetBsdf *)sc, sd->wi, sc->N); + break; + case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: + albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value; + break; + case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: + albedo *= bsdf_principled_hair_albedo(sc); + break; + default: + break; + } +#endif + return albedo; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index be21bcd720e..f16c753d9e2 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -23,8 +23,6 @@ enum MicrofacetType { typedef struct MicrofacetExtra { Spectrum color, cspec0; - Spectrum fresnel_color; - float clearcoat; } MicrofacetExtra; typedef struct MicrofacetBsdf { @@ -184,26 +182,25 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi, * * Else it is simply white */ -ccl_device_forceinline Spectrum reflection_color(ccl_private const MicrofacetBsdf *bsdf, - float3 L, - float3 H) +ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetBsdf *bsdf, + float3 wi, + float3 H) { - Spectrum F = one_spectrum(); - - bool use_clearcoat = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; - bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || use_clearcoat); - - if (use_fresnel) { - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - - F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0); + if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type)) { + return interpolate_fresnel_color(wi, H, bsdf->ior, bsdf->extra->cspec0); } - - if (use_clearcoat) { - F *= 0.25f * bsdf->extra->clearcoat; + else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + return make_spectrum(fresnel_dielectric_cos(dot(wi, H), bsdf->ior)); + } + else { + return one_spectrum(); } +} - return F; +ccl_device_forceinline void bsdf_microfacet_adjust_weight(ccl_private const ShaderData *sd, + ccl_private MicrofacetBsdf *bsdf) +{ + bsdf->sample_weight *= average(microfacet_fresnel(bsdf, sd->wi, bsdf->N)); } /* Generalized Trowbridge-Reitz for clearcoat. */ @@ -292,22 +289,6 @@ ccl_device_inline float bsdf_aniso_D(float alpha_x, float alpha_y, float3 H) } } -ccl_device_forceinline void bsdf_microfacet_fresnel_color(ccl_private const ShaderData *sd, - ccl_private MicrofacetBsdf *bsdf) -{ - kernel_assert(CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type)); - - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - bsdf->extra->fresnel_color = interpolate_fresnel_color( - sd->wi, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0); - - if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { - bsdf->extra->fresnel_color *= 0.25f * bsdf->extra->clearcoat; - } - - bsdf->sample_weight *= average(bsdf->extra->fresnel_color); -} - template<MicrofacetType m_type> ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, const float3 Ng, @@ -380,8 +361,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, *pdf = common / (1.0f + lambdaI); - const Spectrum F = m_refractive ? one_spectrum() : reflection_color(bsdf, wo, H); - + const Spectrum F = microfacet_fresnel(bsdf, wo, H); return F * common / (1.0f + lambdaO + lambdaI); } @@ -463,14 +443,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc, label |= LABEL_SINGULAR; /* Some high number for MIS. */ *pdf = 1e6f; - *eval = make_spectrum(1e6f); - - bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || - bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID); - - if (use_fresnel && !m_refractive) { - *eval *= reflection_color(bsdf, *wo, H); - } + *eval = make_spectrum(1e6f) * microfacet_fresnel(bsdf, *wo, H); } else { label |= LABEL_GLOSSY; @@ -511,8 +484,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc, *pdf = common / (1.0f + lambdaI); - Spectrum F = m_refractive ? one_spectrum() : reflection_color(bsdf, *wo, H); - + Spectrum F = microfacet_fresnel(bsdf, *wo, H); *eval = F * common / (1.0f + lambdaI + lambdaO); } @@ -565,7 +537,7 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID; - bsdf_microfacet_fresnel_color(sd, bsdf); + bsdf_microfacet_adjust_weight(sd, bsdf); return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -573,14 +545,12 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsd ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd) { - bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0); - bsdf->alpha_x = saturatef(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; - bsdf_microfacet_fresnel_color(sd, bsdf); + bsdf_microfacet_adjust_weight(sd, bsdf); return SD_BSDF | SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index defc46a389f..c2ef383f79f 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -401,7 +401,7 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(ccl_private MicrofacetBsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - bsdf_microfacet_fresnel_color(sd, bsdf); + bsdf_microfacet_adjust_weight(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -575,7 +575,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID; - bsdf_microfacet_fresnel_color(sd, bsdf); + bsdf_microfacet_adjust_weight(sd, bsdf); return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h index 91fb9158050..8b595ebfa3b 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h @@ -73,9 +73,8 @@ ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, eval = make_spectrum(val); #endif - float F0 = fresnel_dielectric_cos(1.0f, eta); if (use_fresnel) { - throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0); + throughput = interpolate_fresnel_color(wi, wh, eta, cspec0); eval *= throughput; } @@ -144,11 +143,11 @@ ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, throughput *= color; } else if (use_fresnel && order > 0) { - throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0); + throughput *= interpolate_fresnel_color(wi_prev, wm, eta, cspec0); } #else /* MF_MULTI_GLOSSY */ if (use_fresnel && order > 0) { - throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0); + throughput *= interpolate_fresnel_color(-wr, wm, eta, cspec0); } wr = mf_sample_phase_glossy(-wr, &throughput, wm); #endif @@ -192,8 +191,6 @@ ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float G1_r = 0.0f; bool outside = true; - float F0 = fresnel_dielectric_cos(1.0f, eta); - int order; for (order = 0; order < 10; order++) { /* Sample microfacet height. */ @@ -229,22 +226,12 @@ ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, throughput *= color; } else { - Spectrum t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0); - - if (order == 0) - throughput = t_color; - else - throughput *= t_color; + throughput *= interpolate_fresnel_color(wi_prev, wm, eta, cspec0); } } #else /* MF_MULTI_GLOSSY */ if (use_fresnel) { - Spectrum t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0); - - if (order == 0) - @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs