[Bf-blender-cvs] [4659fa54716] master: Cycles: Scale denoising albedo contribution of Principled BSDFs according to average fresnel

Lukas Stockner noreply at git.blender.org
Wed Nov 27 21:30:05 CET 2019


Commit: 4659fa547166b589cc8e3aef4b8dc699d95547df
Author: Lukas Stockner
Date:   Wed Nov 27 21:22:55 2019 +0100
Branches: master
https://developer.blender.org/rB4659fa547166b589cc8e3aef4b8dc699d95547df

Cycles: Scale denoising albedo contribution of Principled BSDFs according to average fresnel

The Principled BSDF uses Microfacet closures that include a fresnel term,
which are a special case since their weight tends to be near white even
if their average contribution is fairly low.

The sample weight is scaled by the average fresnel weight to account for
this, but the denoising albedo still used the unscaled weight.

This was fine for the original denoiser, but apparently OIDN can't handle
the resulting albedo pass well. Therefore, this commit adds the described
scaling to the albedo pass contribution as well.

This problem was described in T69770.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6289

===================================================================

M	intern/cycles/kernel/closure/bsdf_microfacet.h
M	intern/cycles/kernel/closure/bsdf_microfacet_multi.h
M	intern/cycles/kernel/kernel_passes.h
M	intern/cycles/kernel/svm/svm_types.h

===================================================================

diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 2f73434706c..2884ea62a18 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -37,6 +37,7 @@ CCL_NAMESPACE_BEGIN
 
 typedef ccl_addr_space struct MicrofacetExtra {
   float3 color, cspec0;
+  float3 fresnel_color;
   float clearcoat;
 } MicrofacetExtra;
 
@@ -276,6 +277,22 @@ ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
   return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
 }
 
+ccl_device_forceinline void bsdf_microfacet_fresnel_color(const ShaderData *sd,
+                                                          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->I, 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);
+}
+
 /* GGX microfacet with Smith shadow-masking from:
  *
  * Microfacet Models for Refraction through Rough Surfaces
@@ -305,15 +322,13 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const Sha
 {
   bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
 
-  float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-  float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
-  bsdf->sample_weight *= F;
-
   bsdf->alpha_x = saturate(bsdf->alpha_x);
   bsdf->alpha_y = bsdf->alpha_x;
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
 
+  bsdf_microfacet_fresnel_color(sd, bsdf);
+
   return SD_BSDF | SD_BSDF_HAS_EVAL;
 }
 
@@ -321,15 +336,13 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const S
 {
   bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
 
-  float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-  float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
-  bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
-
   bsdf->alpha_x = saturate(bsdf->alpha_x);
   bsdf->alpha_y = bsdf->alpha_x;
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
 
+  bsdf_microfacet_fresnel_color(sd, bsdf);
+
   return SD_BSDF | SD_BSDF_HAS_EVAL;
 }
 
@@ -364,15 +377,13 @@ ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, con
 {
   bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
 
-  float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-  float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
-  bsdf->sample_weight *= F;
-
   bsdf->alpha_x = saturate(bsdf->alpha_x);
   bsdf->alpha_y = saturate(bsdf->alpha_y);
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
 
+  bsdf_microfacet_fresnel_color(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 9780dd87415..a5fe989bcd1 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -402,9 +402,7 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsd
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
 
-  float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-  float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
-  bsdf->sample_weight *= F;
+  bsdf_microfacet_fresnel_color(sd, bsdf);
 
   return bsdf_microfacet_multi_ggx_common_setup(bsdf);
 }
@@ -424,9 +422,7 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, con
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
 
-  float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-  float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
-  bsdf->sample_weight *= F;
+  bsdf_microfacet_fresnel_color(sd, bsdf);
 
   return bsdf_microfacet_multi_ggx_common_setup(bsdf);
 }
@@ -582,9 +578,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsd
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
 
-  float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-  float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
-  bsdf->sample_weight *= F;
+  bsdf_microfacet_fresnel_color(sd, bsdf);
 
   return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
 }
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index c1d74dddc2a..3e423e42573 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -145,7 +145,17 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
     normal += sc->N * sc->sample_weight;
     sum_weight += sc->sample_weight;
     if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
-      albedo += sc->weight;
+      float3 closure_albedo = sc->weight;
+      /* Closures that include a Fresnel term typically have weights close to 1 even though their
+       * actual contribution is significantly lower.
+       * To account for this, we scale their weight by the average fresnel factor (the same is also
+       * done for the sample weight in the BSDF setup, so we don't need to scale that here). */
+      if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(sc->type)) {
+        MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
+        closure_albedo *= bsdf->extra->fresnel_color;
+      }
+
+      albedo += closure_albedo;
       sum_nonspecular_weight += sc->sample_weight;
     }
   }
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 01710f713ac..aa4dfdca2d1 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -552,6 +552,12 @@ typedef enum ClosureType {
    (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
     type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \
    (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
+#define CLOSURE_IS_BSDF_MICROFACET_FRESNEL(type) \
+  (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \
+   type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \
+   type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \
+   type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID || \
+   type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID)
 #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
 #define CLOSURE_IS_BSSRDF(type) \
   (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)



More information about the Bf-blender-cvs mailing list