[Bf-blender-cvs] [ea1419ea5ed] principled-v2: Add sheen V2 component

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


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

Add sheen V2 component

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

M	intern/cycles/app/cycles_precompute.cpp
M	intern/cycles/kernel/closure/bsdf.h
M	intern/cycles/kernel/closure/bsdf_microfacet_util.h
M	intern/cycles/kernel/closure/bsdf_principled_sheen.h
M	intern/cycles/kernel/film/passes.h
M	intern/cycles/kernel/svm/closure_principled.h
M	intern/cycles/kernel/svm/types.h
M	intern/cycles/kernel/tables.h

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

diff --git a/intern/cycles/app/cycles_precompute.cpp b/intern/cycles/app/cycles_precompute.cpp
index eb5fe2f13f9..5ca0ac0953e 100644
--- a/intern/cycles/app/cycles_precompute.cpp
+++ b/intern/cycles/app/cycles_precompute.cpp
@@ -13,6 +13,7 @@
 
 #include "kernel/closure/bsdf_microfacet.h"
 #include "kernel/closure/bsdf_microfacet_glass.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
 
 #include <iostream>
 
@@ -37,6 +38,35 @@ inline float Sobol2(uint32_t n, uint32_t scramble)
   return ((scramble >> 8) & 0xffffff) / float(1 << 24);
 }
 
+static float precompute_sheen_E(float rough, float mu, float u1, float u2)
+{
+  PrincipledSheenBsdf bsdf;
+  bsdf.weight = one_float3();
+  bsdf.type = CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID;
+  bsdf.sample_weight = 1.0f;
+  bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+  bsdf.roughness = sqr(rough);
+
+  float3 eval, omega_in, domega_in_dx, domega_in_dy;
+  float pdf = 0.0f;
+  bsdf_principled_sheen_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 clamp(average(eval) / pdf, 0.0f, 1e5f);
+  }
+  return 0.0f;
+}
+
 static float precompute_ggx_E(float rough, float mu, float u1, float u2)
 {
   MicrofacetBsdf bsdf;
@@ -144,6 +174,10 @@ bool cycles_precompute(std::string name);
 bool cycles_precompute(std::string name)
 {
   std::map<string, PrecomputeTerm> precompute_terms;
+  precompute_terms["sheen_E"] = {
+      2, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
+        return precompute_sheen_E(rough, mu, u1, u2);
+      }};
   precompute_terms["ggx_E"] = {
       2, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
         return precompute_ggx_E(rough, mu, u1, u2);
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 3a578b9f06e..ef148f5abb4 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -383,6 +383,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
                                              pdf);
       break;
     case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+    case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
       label = bsdf_principled_sheen_sample(sc,
                                            Ng,
                                            sd->I,
@@ -519,6 +520,7 @@ ccl_device_inline
         eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
         break;
       case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+      case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
         eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
         break;
 #  endif /* __PRINCIPLED__ */
@@ -599,6 +601,7 @@ ccl_device_inline
         eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
         break;
       case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+      case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
         eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
         break;
 #  endif /* __PRINCIPLED__ */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index b355c53aaee..bf6c277bc67 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -77,7 +77,7 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(
 }
 
 /* Albedo correction.
- * TODO: Use proper lookup table code for this data. */
+ * TODO: Use proper lookup table code for this data. Also use 0.5px offset. */
 
 ccl_device_forceinline float microfacet_ggx_glass_E(float mu, float rough, float ior)
 {
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
index 3a96a93db73..fa580a540cb 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
@@ -15,6 +15,7 @@ CCL_NAMESPACE_BEGIN
 typedef struct PrincipledSheenBsdf {
   SHADER_CLOSURE_BASE;
   float avg_value;
+  float roughness;
 } PrincipledSheenBsdf;
 
 static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledSheenBsdf),
@@ -50,6 +51,76 @@ calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_priv
   return make_float3(value, value, value);
 }
 
+/* Based on
+ * https://dassaultsystemes-technology.github.io/EnterprisePBRShadingModel/spec-2022x.md.html#components/sheen.
+ */
+ccl_device_inline float sheen_v2_lambda(float mu, float w)
+{
+  float a = lerp(11.9095f, 13.7000f, w);
+  float b = lerp(4.68753f, 2.92754f, w);
+  float c = lerp(0.33467f, 0.28670f, w);
+  float d = lerp(-2.22664f, -0.81757f, w);
+  float e = lerp(-1.76591f, -1.22466f, w);
+
+  float exponent;
+  if (mu < 0.5f) {
+    exponent = a / (1 + b * powf(mu, c)) + d * mu + e;
+  }
+  else {
+    exponent = 2 * a / (1 + b * exp2(-c)) - a / (1 + b * powf(1 - mu, c)) + d * mu + e;
+  }
+  return expf(exponent);
+}
+
+ccl_device_inline float3 sheen_v2_eval(float3 N, float3 V, float3 L, float3 H, float r, float *pdf)
+{
+  float cosNH = dot(N, H), cosNV = dot(N, V), cosNL = dot(N, L);
+
+  if (cosNH < 0 || cosNV < 0 || cosNL < 0) {
+    return zero_float3();
+  }
+
+  /* Evaluate microfacet distribution. */
+  float sinTheta2 = 1 - sqr(cosNH);
+  float invR = 1 / r;
+  float D = M_1_2PI_F * (2 + invR) * powf(sinTheta2, 0.5f * invR);
+
+  /* Evaluate shadowing-masking terms. */
+  float w = -1.59612f / (1 + 0.20375f * fast_safe_powf(r, -0.55825f)) + 1.32805f;
+  float lambdaV = sheen_v2_lambda(cosNV, w);
+  float lambdaL = sheen_v2_lambda(cosNL, w);
+
+  /* Soften shadow terminator. */
+  lambdaL = fast_safe_powf(lambdaL, 1 + 2 * sqr(sqr(sqr(1 - cosNL))));
+
+  /* Combined microfacet BSDF.
+   * Usual form is F*D*G/(4*cosNL*cosNV), but here we have no Fresnel, we skip dividing by cosNL
+   * since Cycles convention is returning BSDF*cosNL, and we use the combined shadowing-masking
+   * term G=1/(1+lambdaV+lambdaL).
+   */
+  float val = D / (4 * cosNV * (1 + lambdaV + lambdaL));
+  return make_float3(val, val, val);
+}
+
+ccl_device_forceinline float sheen_v2_E(float mu, float rough)
+{
+  /* TODO: Cleanup. */
+  rough = saturatef(1 - sqrtf(rough) - 1.0f / 64.0f) * 32.0f;
+  mu = saturatef(mu - 1.0f / 64.0f) * 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_sheen_E[rough_i][mu_i], table_sheen_E[rough_i][mu_i1], mu);
+  float b = lerp(table_sheen_E[rough_i1][mu_i], table_sheen_E[rough_i1][mu_i1], mu);
+  return lerp(a, b, rough);
+}
+
 ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
                                            ccl_private PrincipledSheenBsdf *bsdf)
 {
@@ -59,6 +130,20 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
   return SD_BSDF | SD_BSDF_HAS_EVAL;
 }
 
+ccl_device int bsdf_principled_sheen_v2_setup(ccl_private const ShaderData *sd,
+                                              ccl_private PrincipledSheenBsdf *bsdf)
+{
+  // TODO: Also expose as separate node. Add enum to Velvet BSDF maybe?
+  bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID;
+
+  bsdf->roughness = clamp(bsdf->roughness, 1e-3f, 1.0f);
+
+  bsdf->avg_value = sheen_v2_E(dot(bsdf->N, sd->I), bsdf->roughness);
+  bsdf->sample_weight *= bsdf->avg_value;
+
+  return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
 ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
                                                      const float3 I,
                                                      const float3 omega_in,
@@ -73,7 +158,12 @@ ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClo
 
   if (dot(N, omega_in) > 0.0f) {
     *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
-    return calculate_principled_sheen_brdf(N, V, L, H, pdf);
+    if (bsdf->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID) {
+      return sheen_v2_eval(N, V, L, H, bsdf->roughness, pdf);
+    }
+    else {
+      return calculate_principled_sheen_brdf(N, V, L, H, pdf);
+    }
   }
   else {
     *pdf = 0.0f;
@@ -112,7 +202,12 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
   if (dot(Ng, *omega_in) > 0) {
     float3 H = normalize(I + *omega_in);
 
-    *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf);
+    if (bsdf->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID) {
+      *eval = sheen_v2_eval(N, I, *omega_in, H, bsdf->roughness, pdf);
+    }
+    else {
+      *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf);
+    }
 
 #ifdef __RAY_DIFFERENTIALS__
     // TODO: find a better approximation for the diffuse bounce
diff --git a/intern/cycles/kernel/film/passes.h b/intern/cycles/kernel/film/passes.h
index 1f5cf2048f1..d6562a32cc4 100644
--- a/intern/cycles/kernel/film/passes.h
+++ b/intern/cycles/kernel/film/passes.h
@@ -72,7 +72,7 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
       ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
       closure_albedo *= bsdf->extra->fresnel_color;
     }
-    else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) {
+    else if (CLOSURE_IS_BSDF_SHEEN(sc->type)) {
       ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)sc;
       closure_albedo *= bsdf->avg_value;
     }
diff --git a/intern/cycles/kernel/svm/closure_principled.h b/intern/cycles/kernel/svm/closure_principled.h
index 33476c95f99..9c9e9ebc709 100644
--- a/intern/cycles/kernel/svm/closure_principled.h
+++ b/intern/cycles/kernel/svm/closure_principled.h
@@ -514,6 +514,39 @

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list