[Bf-blender-cvs] [73000c792d4] master: Cycles: Reorganize Fresnel handling in Microfacet closures

Lukas Stockner noreply at git.blender.org
Fri Feb 3 21:12:49 CET 2023


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. @@



More information about the Bf-blender-cvs mailing list