[Bf-blender-cvs] [ea8503c0c5d] principled-v2: Add specular V2 component

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


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

Add specular V2 component

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

M	intern/cycles/kernel/closure/bsdf.h
M	intern/cycles/kernel/closure/bsdf_microfacet.h
M	intern/cycles/kernel/closure/bsdf_microfacet_util.h
M	intern/cycles/kernel/svm/closure_principled.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 ef148f5abb4..e8fb95ab557 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -232,6 +232,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
       break;
     case CLOSURE_BSDF_MICROFACET_GGX_ID:
     case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+    case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
     case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
     case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
       label = bsdf_microfacet_ggx_sample(sc,
@@ -482,6 +483,7 @@ ccl_device_inline
         break;
       case CLOSURE_BSDF_MICROFACET_GGX_ID:
       case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+      case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
       case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
       case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
         eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
@@ -563,6 +565,7 @@ ccl_device_inline
         break;
       case CLOSURE_BSDF_MICROFACET_GGX_ID:
       case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+      case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
       case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
       case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
         eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
@@ -629,6 +632,7 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
   switch (sc->type) {
     case CLOSURE_BSDF_MICROFACET_GGX_ID:
     case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+    case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
     case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
     case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
     case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 904640356ef..ebe13ec6a33 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -18,6 +18,18 @@ typedef struct MicrofacetExtra {
   float3 fresnel_color;
 } MicrofacetExtra;
 
+typedef struct MicrofacetExtrav2 {
+  /* Metallic fresnel control */
+  float3 metal_base, metal_edge;
+  float metal_falloff;
+  float dielectric;
+} MicrofacetExtrav2;
+
+// TODO probably remove this for the final code
+static_assert(sizeof(MicrofacetExtra) <= sizeof(ShaderClosure), "Try to shrink MicrofacetExtra!");
+static_assert(sizeof(MicrofacetExtrav2) <= sizeof(ShaderClosure),
+              "Try to shrink MicrofacetExtra!");
+
 typedef struct MicrofacetBsdf {
   SHADER_CLOSURE_BASE;
 
@@ -45,6 +57,19 @@ ccl_device_forceinline float3 reflection_color(ccl_private const MicrofacetBsdf
   else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
     return interpolate_fresnel_color(L, H, bsdf->ior, make_float3(0.04f, 0.04f, 0.04f));
   }
+  else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID) {
+    MicrofacetExtrav2 *extra = (MicrofacetExtrav2*) bsdf->extra;
+    float cosHL = dot(H, L);
+    /* Metallic Fresnel: Kinda Schlick-Fresnel-like with configurable F0 and F90
+     * as well as falloff control. F90=white and falloff=0.2 gives classic Schlick Fresnel.
+     * Metallic factor and albedo scaling is baked into the F0 and F90 parameters. */
+    float metallicBlend = powf(1.0f - cosHL, extra->metal_falloff);
+    float3 metallic = lerp(extra->metal_base, extra->metal_edge, metallicBlend);
+    /* Dielectric Fresnel, just basic IOR control. */
+    float dielectric = extra->dielectric * fresnel_dielectric_cos(cosHL, bsdf->ior);
+
+    return metallic + make_float3(dielectric, dielectric, dielectric);
+  }
   else {
     return one_float3();
   }
@@ -80,6 +105,18 @@ ccl_device_inline float3 microfacet_ggx_albedo_scaling(ccl_private const Microfa
   /* TODO: Ensure that increase in weight does not mess up glossy color, albedo etc. passes */
 }
 
+ccl_device_inline float microfacet_ggx_albedo_scaling_float(ccl_private const MicrofacetBsdf *bsdf,
+                                                            ccl_private const ShaderData *sd,
+                                                            const float Fss)
+{
+  // TOOD: Deduplicate somehow?
+  float mu = dot(sd->I, bsdf->N);
+  float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
+  float E = microfacet_ggx_E(mu, rough), E_avg = microfacet_ggx_E_avg(rough);
+  float Fms = Fss * E_avg / (1.0f - Fss * (1.0f - E_avg));
+  return 1.0f + Fms * ((1.0f - E) / E);
+}
+
 ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
 {
   bsdf->extra = NULL;
@@ -131,6 +168,46 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(ccl_private MicrofacetBsd
   return bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
 }
 
+ccl_device int bsdf_microfacet_ggx_fresnel_v2_setup(ccl_private MicrofacetBsdf *bsdf,
+                                                    ccl_private const ShaderData *sd,
+                                                    float metallic,
+                                                    float dielectric)
+{
+  bsdf->alpha_x = saturatef(bsdf->alpha_x);
+  bsdf->alpha_y = saturatef(bsdf->alpha_y);
+
+  MicrofacetExtrav2 *extra = (MicrofacetExtrav2*) bsdf->extra;
+
+  if (metallic > 0.0f) {
+    extra->metal_base = saturate(extra->metal_base);
+    extra->metal_edge = saturate(extra->metal_edge);
+    extra->metal_falloff = 1.0f / clamp(extra->metal_falloff, 1e-3f, 1.0f);
+    float3 metal_Fss = metallic_Fss(extra->metal_base, extra->metal_edge, extra->metal_falloff);
+    float3 metal_scale = microfacet_ggx_albedo_scaling(bsdf, sd, metal_Fss);
+    extra->metal_base *= metallic * metal_scale;
+    extra->metal_edge *= metallic * metal_scale;
+  }
+  else {
+    extra->metal_falloff = 0.0f;
+    extra->metal_base = zero_float3();
+    extra->metal_edge = zero_float3();
+  }
+
+  if (dielectric > 0.0f) {
+    float dielectric_Fss = dielectric_fresnel_Fss(bsdf->ior);
+    extra->dielectric = dielectric * microfacet_ggx_albedo_scaling_float(bsdf, sd, dielectric_Fss);
+  }
+  else {
+    extra->dielectric = 0.0f;
+  }
+
+  bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID;
+
+  // bsdf_microfacet_fresnel_color(sd, bsdf); // TODO
+
+  return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
 ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *bsdf,
                                                    ccl_private const ShaderData *sd)
 {
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index bf6c277bc67..d8a7b5f9a87 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -137,6 +137,12 @@ ccl_device_forceinline float microfacet_ggx_E_avg(float rough)
   return lerp(table_ggx_E_avg[rough_i], table_ggx_E_avg[rough_i1], rough);
 }
 
+ccl_device_inline float3 metallic_Fss(float3 F0, float3 F90, float falloff)
+{
+  /* Fss for lerp(F0, F90, (1-cosNI)^falloff) */
+  return lerp(F0, F90, 2.0f / (sqr(falloff) + 3*falloff + 2));
+}
+
 ccl_device_inline float3 schlick_fresnel_Fss(float3 F0)
 {
   /* TODO validate using multiGGX code */
@@ -144,7 +150,7 @@ ccl_device_inline float3 schlick_fresnel_Fss(float3 F0)
 }
 
 /* TODO Imageworks source */
-ccl_device_inline float3 dielectic_fresnel_Fss(float eta)
+ccl_device_inline float dielectric_fresnel_Fss(float eta)
 {
   /* TODO validate using multiGGX code */
   float f;
@@ -154,7 +160,7 @@ ccl_device_inline float3 dielectic_fresnel_Fss(float eta)
   else {
     f = (eta - 1.0f) / (4.08567f + 1.00071f * eta);
   }
-  return make_float3(f, f, f);
+  return f;
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/closure_principled.h b/intern/cycles/kernel/svm/closure_principled.h
index 9970cb2d9e6..c8d6f5211cb 100644
--- a/intern/cycles/kernel/svm/closure_principled.h
+++ b/intern/cycles/kernel/svm/closure_principled.h
@@ -127,9 +127,9 @@ ccl_device_inline void principled_v1_specular(KernelGlobals kg,
   }
 
   float anisotropic = stack_load_float(stack, aniso_offset);
-  float3 T = stack_valid(tangent_offset) ? stack_load_float3(stack, tangent_offset) :
-                                           zero_float3();
-  if (stack_valid(rotation_offset)) {
+  float3 T = zero_float3();
+  if (stack_valid(tangent_offset)) {
+    T = stack_load_float3(stack, tangent_offset);
     T = rotate_around_axis(T, N, stack_load_float(stack, rotation_offset) * M_2PI_F);
   }
 
@@ -544,6 +544,69 @@ ccl_device_inline float principled_v2_sheen(KernelGlobals kg,
   return sheen * bsdf->avg_value; // TODO include tint
 }
 
+ccl_device_inline float principled_v2_specular(ccl_private ShaderData *sd,
+                                               ccl_private float *stack,
+                                               float3 weight,
+                                               float3 base_color,
+                                               float roughness,
+                                               float metallic,
+                                               float ior,
+                                               float transmission,
+                                               float3 N,
+                                               uint data1,
+                                               uint data2)
+{
+  // TODO Handle caustics flag
+
+  uint falloff_offset, edge_offset, dummy;
+  uint aniso_offset, rotation_offset, tangent_offset;
+  svm_unpack_node_uchar4(data1, &falloff_offset, &edge_offset, &dummy, &dummy);
+  svm_unpack_node_uchar4(data2, &aniso_offset, &rotation_offset, &tangent_offset, &dummy);
+
+  /* This function handles two specular components:
+   * 1. Metallic: The overall energy is given by the metallic input
+   * 2. Dielectric opaque: The overall energy is given by (1-metallic)*(1-transmission)
+   * Both of these are handled by one closure, which adds up two Fresnel terms.
+   * On top of that, there is also the transmissive component, that is handled by the glass code.
+   */
+
+  float anisotropic = stack_load_float(stack, aniso_offset);
+  float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
+  float3 T = zer

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list