[Bf-blender-cvs] [dbdd2bb4545] principled-v2: Add energy compensation for specular component

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


Commit: dbdd2bb454559a757b007cfddfa773326751fc2d
Author: Lukas Stockner
Date:   Mon Jul 4 23:31:48 2022 +0200
Branches: principled-v2
https://developer.blender.org/rBdbdd2bb454559a757b007cfddfa773326751fc2d

Add energy compensation for specular component

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

M	intern/cycles/app/cycles_precompute.cpp
M	intern/cycles/kernel/closure/bsdf_microfacet_util.h
M	intern/cycles/kernel/svm/closure_principled.h
M	intern/cycles/kernel/tables.h

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

diff --git a/intern/cycles/app/cycles_precompute.cpp b/intern/cycles/app/cycles_precompute.cpp
index 5ca0ac0953e..1b399df3d01 100644
--- a/intern/cycles/app/cycles_precompute.cpp
+++ b/intern/cycles/app/cycles_precompute.cpp
@@ -165,6 +165,49 @@ static float precompute_ggx_glass_E(
   return 0.0f;
 }
 
+static float precompute_ggx_dielectric_E(float rough, float mu, float eta, float u1, float u2)
+{
+  // TODO: Reparametrize based on fresnel_dielectric_cos(mu, eta) instead of mu to get more resolution?
+  // Probably need lerp(mu, fresnel_dielectric_cos(mu, eta), 0.9) or so because of flat IOR region.
+  MicrofacetExtrav2 extra;
+  MicrofacetBsdf bsdf;
+  bsdf.weight = one_float3();
+  bsdf.type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID;
+  bsdf.sample_weight = 1.0f;
+  bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+  bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
+  bsdf.ior = eta;
+  bsdf.extra = (MicrofacetExtra *)&extra;
+  bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
+  extra.metal_base = extra.metal_edge = zero_float3();
+  extra.metal_falloff = 0.0f;
+
+  /* Dependency warning - this relies on the ggx_E and ggx_E_avg lookup tables! */
+  float E = microfacet_ggx_E(mu, rough), E_avg = microfacet_ggx_E_avg(rough);
+  float Fss = dielectric_fresnel_Fss(eta);
+  float Fms = Fss * E_avg / (1.0f - Fss * (1.0f - E_avg));
+  extra.dielectric = 1.0f + Fms * ((1.0f - E) / E);
+
+  float3 eval, omega_in, domega_in_dx, domega_in_dy;
+  float pdf = 0.0f;
+  bsdf_microfacet_ggx_sample((ShaderClosure *)&bsdf,
+                             make_float3(0.0f, 0.0f, 1.0f),
+                             make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+                             zero_float3(),
+                             zero_float3(),
+                             u1,
+                             u2,
+                             &eval,
+                             &omega_in,
+                             &domega_in_dx,
+                             &domega_in_dy,
+                             &pdf);
+  if (pdf != 0.0f) {
+    return average(eval) / pdf;
+  }
+  return 0.0f;
+}
+
 struct PrecomputeTerm {
   int dim, samples, res;
   std::function<float(float, float, float, float, float, uint *)> evaluation;
@@ -202,6 +245,15 @@ bool cycles_precompute(std::string name)
       3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
         return precompute_ggx_refract_E(rough, mu, 1.0f / ior, u1, u2);
       }};
+  precompute_terms["ggx_dielectric_E"] = {
+      3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
+        return precompute_ggx_dielectric_E(rough, mu, ior, u1, u2);
+      }};
+  // TODO: Consider more X resolution for this table.
+  precompute_terms["ggx_dielectric_inv_E"] = {
+      3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
+        return precompute_ggx_dielectric_E(rough, mu, 1.0f / ior, u1, u2);
+      }};
 
   if (precompute_terms.count(name) == 0) {
     return false;
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index d8a7b5f9a87..509cd6708ec 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -110,6 +110,37 @@ ccl_device_forceinline float microfacet_ggx_glass_E(float mu, float rough, float
   return lerp(lerp(a, b, rough), lerp(c, d, rough), ior);
 }
 
+ccl_device_forceinline float microfacet_ggx_dielectric_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_dielectric_inv_E : table_ggx_dielectric_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;
diff --git a/intern/cycles/kernel/svm/closure_principled.h b/intern/cycles/kernel/svm/closure_principled.h
index c8d6f5211cb..8074646386d 100644
--- a/intern/cycles/kernel/svm/closure_principled.h
+++ b/intern/cycles/kernel/svm/closure_principled.h
@@ -604,7 +604,7 @@ ccl_device_inline float principled_v2_specular(ccl_private ShaderData *sd,
   float dielectric = (1.0f - metallic) * (1.0f - transmission);
   sd->flag |= bsdf_microfacet_ggx_fresnel_v2_setup(bsdf, sd, metallic, dielectric);
 
-  return 0.0f;  // TODO energy conservation
+  return microfacet_ggx_dielectric_E(dot(sd->I, N), roughness, ior);
 }
 
 ccl_device void svm_node_closure_principled_v2(KernelGlobals kg,
@@ -637,22 +637,22 @@ ccl_device void svm_node_closure_principled_v2(KernelGlobals kg,
   weight *= 1.0f - principled_v2_clearcoat(kg, sd, stack, weight, path_flag, node_2.w);
   weight *= 1.0f - principled_v2_sheen(kg, sd, stack, weight, N, node_2.z);
 
-  principled_v2_specular(sd,
-                         stack,
-                         weight,
-                         base_color,
-                         roughness,
-                         metallic,
-                         ior,
-                         transmission,
-                         N,
-                         node_2.x,
-                         node_2.y);
+  float dielectric_albedo = principled_v2_specular(sd,
+                                                   stack,
+                                                   weight,
+                                                   base_color,
+                                                   roughness,
+                                                   metallic,
+                                                   ior,
+                                                   transmission,
+                                                   N,
+                                                   node_2.x,
+                                                   node_2.y);
   weight *= 1.0f - metallic;
 
   // TODO Glass
 
-  weight *= 1.0f - transmission;
+  weight *= (1.0f - transmission) * (1.0f - dielectric_albedo);
 
   principled_v2_diffuse(sd, weight, base_color, 1.0f, N);
 }
diff --git a/intern/cycles/kernel/tables.h b/intern/cycles/kernel/tables.h
index 1ba1b7a9f9b..169ef40142a 100644
--- a/intern/cycles/kernel/tables.h
+++ b/intern/cycles/kernel/tables.h
@@ -720,4 +720,586 @@ static const float table_sheen_E[32][32] = {
     {0.591225f, 0.045818f, 0.00732363f, 0.00112657f, 0.000170285f, 2.07311e-05f, 2.37514e-06f, 1.86339e-07f, 1.1563e-08f, 7.84983e-10f, 2.46995e-11f, 1.01276e-12f, 2.0924e-14f, 2.83508e-16f, 7.15504e-18f, 2.95273e-20f, 8.42547e-23f, 2.83875e-25f, 9.54702e-28f, 5.32362e-31f, 4.20998e-34f, 1.43471e-37f, 3.92305e-40f, 1.4013e-45f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}
 };
 
+static const float table_ggx_dielectric_E[16][16][16] = {
+  {
+    {0.000415471f, 0.000132454f, 6.02304e-05f, 3.2349e-05f, 1.89411e-05f, 1.21628e-05f, 8.25374e-06f, 5.85431e-06f, 4.37281e-06f, 3.34566e-06f, 2.63778e-06f, 2.15633e-06f, 1.80054e-06f, 1.53889e-06f, 1.35031e-06f, 1.20534e-06f},
+    {0.000500569f, 0.000167997f, 7.57408e-05f, 4.05907e-05f, 2.42137e-05f, 1.5401e-05f, 1.04112e-05f, 7.33722e-06f, 5.39029e-06f, 4.09224e-06f, 3.22436e-06f, 2.60533e-06f, 2.16446e-06f, 1.84878e-06f, 1.62258e-06f, 1.45125e-06f},
+    {0.000631643f, 0.000217958f, 0.000100288f, 5.3289e-05f, 3.109e-05f, 1.96765e-05f, 1.32621e-05f, 9.20107e-06f, 6.70118e-06f, 5.04004e-06f, 3.89982e-06f, 3.12116e-06f, 2.58227e-06f, 2.18829e-06f, 1.91778e-06f, 1.72415e-06f},
+    {0.000807995f, 0.000285155f, 0.000131307f, 6.98269e-05f, 4.08318e-05f, 2.54499e-05f, 1.68666e-05f, 1.16319e-05f, 8.38762e-06f, 6.13532e-06f, 4.71284e-06f, 3.71552e-06f, 3.0378e-06f, 2.55783e-06f, 2.22496e-06f, 2.0118e-06f},
+    {0.00106589f, 0.00038733f, 0.000176011f, 9.36545e-05f, 5.3984e-05f, 3.35446e-05f, 2.19039e-05f, 1.48318e-05f, 1.03839e-05f, 7.52919e-06f, 5.65876e-06f, 4.39196e-06f, 3.50482e-06f, 2.94163e-06f, 2.53876e-06f, 2.29142e-06f},
+    {0.001453f, 0.00053215f, 0.000243545f, 0.000126661f, 7.22715e-05f, 4.4385e-05f, 2.8361e-05f, 1.87374e-05f, 1.29863e-05f, 9.20271e-06f, 6.69805e-06f, 5.08628e-06f, 3.99503e-06f, 3.29186e-06f, 2.82329e-06f, 2.54467e-06f},
+    {0.0020343f, 0.000748349f, 0.000339965f, 0.000174612f, 9.84092e-05f, 5.88162e-05f, 3.66575e-05f, 2.38413e-05f, 1.5922e-05f, 1.09605e-05f, 7.79514e-06f, 5.76436e-06f, 4.44091e-06f, 3.59403e-06f, 3.06771e-06f, 2.75371e-06f},
+    {0.00300857f, 0.0010926f, 0.000491688f, 0.000246388f, 0.000134689f, 7.80441e-05f, 4.756e-05f, 2.97255e-05f, 1.92082e-05f, 1.28153e-05f, 8.84601e-06f, 6.32998e-06f, 4.78029e-06f, 3.81701e-06f, 3.24172e-06f, 2.92231e-06f},
+    {0.00456566f, 0.00165612f, 0.000718974f, 0.000348896f, 0.000183809f, 0.000102446f, 5.97574e-05f, 3.61011e-05f, 2.23647e-05f, 1.44132e-05f, 9.60647e-06f, 6.68339e-06f, 4.95371e-06f, 3.90912e-06f, 3.32515e-06f, 3.0115e-06f},
+    {0.00738665f, 0.00259509f, 0.00107763f, 0.000497453f, 0.000248034f, 0.000130573f, 7.24356e-05f, 4.14835e-05f, 2.48774e-05f, 1.54146e-05f, 9.95278e-06f, 6.78691e-06f, 4.96036e-06f, 3.92023e-06f, 3.34373e-06f, 3.06328e-06f},
+    {0.0125017f, 0.00419002f, 0.00162011f, 0.000690663f, 0.000319282f, 0.0001576f, 8.20314e-05f, 4.51641e-05f, 2.59064e-05f, 1.55605e-05f, 9.81415e-06f, 6.6463e-06f, 4.8242e-06f, 3.83793e-06f, 3.3166e-06f, 3.07314e-06f},
+    {0.0224401f, 0.00691917f, 0.00236534f, 0.000899984f, 0.000378675f, 0.00017348f, 8.60665e-05f, 4.56151e-05f, 2.54936e-05f, 1.5027e-05f, 9.41134e-06f, 6.33024e-06f, 4.63698e-06f, 3.73457e-06

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list