[Bf-blender-cvs] [690f7c18317] principled-v2: Use albedo-scaling correction for "multiscattering" GGX closures

Lukas Stockner noreply at git.blender.org
Mon Jul 4 23:56:12 CEST 2022


Commit: 690f7c18317ccf44855e96dd02eba42cb213a80c
Author: Lukas Stockner
Date:   Mon Jul 4 23:31:47 2022 +0200
Branches: principled-v2
https://developer.blender.org/rB690f7c18317ccf44855e96dd02eba42cb213a80c

Use albedo-scaling correction for "multiscattering" GGX closures

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

M	intern/cycles/kernel/closure/bsdf_microfacet.h
M	intern/cycles/kernel/closure/bsdf_microfacet_glass.h
M	intern/cycles/kernel/closure/bsdf_microfacet_util.h
M	intern/cycles/kernel/tables.h

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

diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 4a4c01b8117..780041c2a52 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -67,6 +67,25 @@ ccl_device_forceinline void bsdf_microfacet_fresnel_color(ccl_private const Shad
   bsdf->sample_weight *= average(bsdf->extra->fresnel_color);
 }
 
+ccl_device_inline float3 microfacet_ggx_albedo_scaling(ccl_private const MicrofacetBsdf *bsdf,
+                                                       ccl_private const ShaderData *sd,
+                                                       const float3 Fss)
+{
+  float mu = dot(sd->I, bsdf->N);
+  float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
+  float E = microfacet_ggx_E(mu, rough);
+
+  float E_avg = microfacet_ggx_E_avg(rough);
+  /* Fms here is based on the appendix of
+   * https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf,
+   * with one Fss cancelled out since this is just a multiplier on top of
+   * the single-scattering BSDF, which already contains one bounce of Fresnel. */
+  float3 Fms = Fss * E_avg / (one_float3() - Fss * (1.0f - E_avg));
+
+  return one_float3() + Fms * ((1.0f - E) / E);
+  /* TODO: Ensure that increase in weight does not mess up glossy color, albedo etc. passes */
+}
+
 ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
 {
   bsdf->extra = NULL;
@@ -91,6 +110,7 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(ccl_private MicrofacetBsdf *bsdf,
                                                ccl_private const ShaderData *sd,
                                                const float3 color)
 {
+  bsdf->weight *= microfacet_ggx_albedo_scaling(bsdf, sd, saturate(color));
   return bsdf_microfacet_ggx_setup(bsdf);
 }
 
@@ -112,6 +132,8 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsd
 ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsdf,
                                                        ccl_private const ShaderData *sd)
 {
+  float3 Fss = schlick_fresnel_Fss(bsdf->extra->cspec0);
+  bsdf->weight *= microfacet_ggx_albedo_scaling(bsdf, sd, Fss);
   return bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
 }
 
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_glass.h b/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
index d1e3f178275..e302e482443 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
@@ -5,6 +5,24 @@
 
 CCL_NAMESPACE_BEGIN
 
+ccl_device_inline float3 microfacet_ggx_glass_albedo_scaling(
+    ccl_private const ShaderData *sd, ccl_private const MicrofacetBsdf *bsdf, const float3 Fss)
+{
+  float mu = dot(sd->I, bsdf->N);
+  float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
+  float E = microfacet_ggx_glass_E(mu, rough, bsdf->ior);
+
+  /* Close enough for glass, coloring here is unphysical anyways and it's unclear how to
+   * approximate it better. */
+  float3 Fms = Fss;
+
+  return one_float3() + Fms * ((1.0f - E) / E);
+  /* TODO: Ensure that increase in weight does not mess up glossy color, albedo etc. passes */
+}
+
+/* Currently no non-albedo-scaled version is implemented, could easily be added
+ * but would still break compatibility with the old glass due to the microfacet Fresnel. */
+
 ccl_device int bsdf_microfacet_multi_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf,
                                                      ccl_private const ShaderData *sd,
                                                      const float3 color)
@@ -16,6 +34,8 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(ccl_private MicrofacetBsdf
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
 
+  bsdf->weight *= microfacet_ggx_glass_albedo_scaling(sd, bsdf, saturate(color));
+
   return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
 }
 
@@ -31,6 +51,9 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa
 
   bsdf_microfacet_fresnel_color(sd, bsdf);
 
+  float3 Fss = schlick_fresnel_Fss(bsdf->extra->cspec0);
+  bsdf->weight *= microfacet_ggx_glass_albedo_scaling(sd, bsdf, Fss);
+
   return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
 }
 
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index a873507d201..f660cdb6f04 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -76,4 +76,70 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(
   return normalize(make_float3(alpha_x * Mh.x, alpha_y * Mh.y, max(0.0f, Mh.z)));
 }
 
+/* Albedo correction.
+ * TODO: Use proper lookup table code for this data. */
+
+ccl_device_forceinline float microfacet_ggx_glass_E(float mu, float rough, float ior)
+{
+  bool inv_table = (ior < 1.0f);
+  if (inv_table) {
+    ior = 1.0f / ior;
+  }
+
+  rough = saturatef(1 - rough) * 16.0f;
+  mu = saturatef(mu) * 16.0f;
+  ior = saturatef(sqrtf(0.5f * (ior - 1.0f))) * 16.0f;
+
+  int rough_i = min(15, (int)rough);
+  int rough_i1 = min(15, rough_i + 1);
+  int mu_i = min(15, (int)mu);
+  int mu_i1 = min(15, mu_i + 1);
+  int ior_i = min(15, (int)ior);
+  int ior_i1 = min(15, ior_i + 1);
+
+  rough -= rough_i;
+  mu -= mu_i;
+  ior -= ior_i;
+
+  auto &table = inv_table ? table_ggx_glass_inv_E : table_ggx_glass_E;
+  float a = lerp(table[ior_i][rough_i][mu_i], table[ior_i][rough_i][mu_i1], mu);
+  float b = lerp(table[ior_i][rough_i1][mu_i], table[ior_i][rough_i1][mu_i1], mu);
+  float c = lerp(table[ior_i1][rough_i][mu_i], table[ior_i1][rough_i][mu_i1], mu);
+  float d = lerp(table[ior_i1][rough_i1][mu_i], table[ior_i1][rough_i1][mu_i1], mu);
+
+  return lerp(lerp(a, b, rough), lerp(c, d, rough), ior);
+}
+
+ccl_device_forceinline float microfacet_ggx_E(float mu, float rough)
+{
+  rough = saturatef(1 - rough) * 32.0f;
+  mu = saturatef(mu) * 32.0f;
+
+  int rough_i = min(31, (int)rough);
+  int rough_i1 = min(31, rough_i + 1);
+  int mu_i = min(31, (int)mu);
+  int mu_i1 = min(31, mu_i + 1);
+
+  rough -= rough_i;
+  mu -= mu_i;
+
+  float a = lerp(table_ggx_E[rough_i][mu_i], table_ggx_E[rough_i][mu_i1], mu);
+  float b = lerp(table_ggx_E[rough_i1][mu_i], table_ggx_E[rough_i1][mu_i1], mu);
+  return lerp(a, b, rough);
+}
+
+ccl_device_forceinline float microfacet_ggx_E_avg(float rough)
+{
+  rough = saturatef(1 - rough) * 32.0f;
+  int rough_i = min(31, (int)rough);
+  int rough_i1 = min(31, rough_i + 1);
+  rough -= rough_i;
+  return lerp(table_ggx_E_avg[rough_i], table_ggx_E_avg[rough_i1], rough);
+}
+
+ccl_device_inline float3 schlick_fresnel_Fss(float3 F0)
+{
+  return (one_float3() + 20.0f * saturate(F0)) * (1.0f / 21.0f);
+}
+
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/tables.h b/intern/cycles/kernel/tables.h
index c1fdbba3fa7..9444e459707 100644
--- a/intern/cycles/kernel/tables.h
+++ b/intern/cycles/kernel/tables.h
@@ -63,4 +63,626 @@ ccl_inline_constant float cie_colour_match[][3] = {
   {0.0001f, 0.0000f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f}, {0.0000f, 0.0000f, 0.0000f}
 };
 
+static const float table_ggx_E[32][32] = {
+    {0.938993f, 0.858736f, 0.800571f, 0.753374f, 0.713238f, 0.678442f, 0.647723f, 0.620302f, 0.595405f, 0.573038f, 0.552392f, 0.533285f, 0.515945f, 0.499677f, 0.484473f, 0.470426f, 0.457164f, 0.444816f, 0.433116f, 0.422004f, 0.411722f, 0.401847f, 0.392444f, 0.383611f, 0.375193f, 0.367147f, 0.359387f, 0.352163f, 0.345223f, 0.338525f, 0.332036f, 0.325866f},
+    {0.942738f, 0.866279f, 0.811134f, 0.766195f, 0.727883f, 0.694788f, 0.665388f, 0.639283f, 0.615624f, 0.594017f, 0.574515f, 0.556419f, 0.539656f, 0.524166f, 0.509889f, 0.496369f, 0.483729f, 0.471968f, 0.460875f, 0.450365f, 0.440542f, 0.431178f, 0.422252f, 0.41389f, 0.405924f, 0.398354f, 0.391047f, 0.384224f, 0.377665f, 0.371384f, 0.365363f, 0.359468f},
+    {0.946178f, 0.873743f, 0.821452f, 0.778574f, 0.742257f, 0.710809f, 0.682893f, 0.657944f, 0.635623f, 0.615179f, 0.596415f, 0.579404f, 0.56365f, 0.548923f, 0.535197f, 0.522582f, 0.510837f, 0.499666f, 0.489196f, 0.479435f, 0.470211f, 0.461503f, 0.4532f, 0.445456f, 0.438062f, 0.431058f, 0.424383f, 0.418092f, 0.412088f, 0.406399f, 0.40087f, 0.39569f},
+    {0.949756f, 0.881149f, 0.831485f, 0.790608f, 0.756361f, 0.726391f, 0.7001f, 0.676466f, 0.655176f, 0.636031f, 0.618395f, 0.602169f, 0.587374f, 0.573694f, 0.560934f, 0.549078f, 0.537966f, 0.52764f, 0.518107f, 0.509184f, 0.500732f, 0.492642f, 0.485138f, 0.478096f, 0.471514f, 0.465218f, 0.459228f, 0.453642f, 0.448353f, 0.443399f, 0.438603f, 0.434138f},
+    {0.953417f, 0.888246f, 0.840978f, 0.802406f, 0.770036f, 0.741652f, 0.716727f, 0.694556f, 0.674474f, 0.656312f, 0.639932f, 0.624841f, 0.610947f, 0.598109f, 0.586429f, 0.575584f, 0.565512f, 0.556085f, 0.547336f, 0.539137f, 0.531419f, 0.524487f, 0.517923f, 0.511844f, 0.506034f, 0.500635f, 0.495476f, 0.49075f, 0.486239f, 0.482136f, 0.478268f, 0.474605f},
+    {0.956708f, 0.895075f, 0.849858f, 0.813821f, 0.783021f, 0.756452f, 0.732847f, 0.711996f, 0.6933f, 0.67629f, 0.660854f, 0.646985f, 0.634265f, 0.622532f, 0.61175f, 0.601824f, 0.592715f, 0.584454f, 0.576767f, 0.569631f, 0.563046f, 0.556973f, 0.551345f, 0.546069f, 0.541248f, 0.536783f, 0.532655f, 0.528942f, 0.525551f, 0.52244f, 0.519561f, 0.516886f},
+    {0.959787f, 0.901339f, 0.858526f, 0.824767f, 0.795491f, 0.770587f, 0.748376f, 0.728728f, 0.71134f, 0.695646f, 0.681395f, 0.6685f, 0.656868f, 0.646354f, 0.636793f, 0.628025f, 0.620035f, 0.612715f, 0.606052f, 0.599955f, 0.594453f, 0.589562f, 0.585089f, 0.581059f, 0.577338f, 0.574072f, 0.5711f, 0.568439f, 0.566075f, 0.563943f, 0.562054f, 0.560442f},
+    {0.962795f, 0.906868f, 0.866905f, 0.835062f, 0.807402f, 0.783716f, 0.763213f, 0.744831f, 0.728521f, 0.714133f, 0.701219f, 0.689528f, 0.679048f, 0.669662f, 0.661165f, 0.653617f, 0.646934f, 0.640853f, 0.635463f, 0.630651f, 0.626301f, 0.622531f, 0.619196f, 0.616271f, 0.613734f, 0.611499f, 0.609711f, 0.608151f, 0.606875f, 0.605871f, 0.605133f, 0.604569f},
+    {0.965348f, 0.911877f, 0.87486f, 0.844371f, 0.818636f, 0.796204f, 0.77703f, 0.760093f,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list