[Bf-blender-cvs] [552abb838c7] principled-v2: Replace metallic Fresnel with F82 model

Lukas Stockner noreply at git.blender.org
Sun Jul 24 03:54:26 CEST 2022


Commit: 552abb838c76d44a0d7d1226b59a1ab381e88386
Author: Lukas Stockner
Date:   Sun Jul 24 03:40:57 2022 +0200
Branches: principled-v2
https://developer.blender.org/rB552abb838c76d44a0d7d1226b59a1ab381e88386

Replace metallic Fresnel with F82 model

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

M	intern/cycles/app/cycles_precompute.cpp
M	intern/cycles/kernel/closure/bsdf_microfacet.h
M	intern/cycles/kernel/closure/bsdf_microfacet_util.h
M	intern/cycles/kernel/closure/bsdf_util.h
M	intern/cycles/kernel/svm/closure_principled.h
M	intern/cycles/scene/shader_nodes.cpp
M	intern/cycles/scene/shader_nodes.h
M	source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
M	source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc

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

diff --git a/intern/cycles/app/cycles_precompute.cpp b/intern/cycles/app/cycles_precompute.cpp
index 4ce62d2298a..26be3f16f3a 100644
--- a/intern/cycles/app/cycles_precompute.cpp
+++ b/intern/cycles/app/cycles_precompute.cpp
@@ -242,8 +242,7 @@ static float precompute_ggx_dielectric_E(float rough, float mu, float eta, float
   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;
+  extra.metallic = extra.metal_base = extra.metal_edge_factor = zero_float3();
 
   /* 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);
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 5c7e70181d7..4fe36b5f235 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -19,8 +19,8 @@ typedef struct MicrofacetExtra {
 
 typedef struct MicrofacetExtrav2 {
   /* Metallic fresnel control */
-  float3 metal_base, metal_edge;
-  float metal_falloff;
+  float3 metal_base, metal_edge_factor;
+  float3 metallic;
   float dielectric;
 } MicrofacetExtrav2;
 
@@ -66,8 +66,8 @@ ccl_device_forceinline float3 reflection_color(ccl_private const MicrofacetBsdf
     /* 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 = mix(extra->metal_base, extra->metal_edge, metallicBlend);
+    float3 metallic = extra->metallic *
+                      fresnel_metallic(extra->metal_base, extra->metal_edge_factor, cosHL);
     /* Dielectric Fresnel, just basic IOR control. */
     float dielectric = extra->dielectric * fresnel_dielectric_cos(cosHL, bsdf->ior);
 
@@ -187,18 +187,13 @@ ccl_device int bsdf_microfacet_ggx_fresnel_v2_setup(KernelGlobals kg,
   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(kg, bsdf, sd, metal_Fss);
-    extra->metal_base *= metallic * metal_scale;
-    extra->metal_edge *= metallic * metal_scale;
+    float3 metal_Fss = fresnel_metallic_Fss(extra->metal_base, extra->metal_edge_factor);
+    extra->metallic = metallic * microfacet_ggx_albedo_scaling(kg, bsdf, sd, metal_Fss);
   }
   else {
-    extra->metal_falloff = 0.0f;
+    extra->metallic = zero_float3();
     extra->metal_base = zero_float3();
-    extra->metal_edge = zero_float3();
+    extra->metal_edge_factor = zero_float3();
   }
 
   if (dielectric > 0.0f) {
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index a1399bff5fe..a5c77763133 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -131,16 +131,14 @@ ccl_device_forceinline float clearcoat_E(KernelGlobals kg, float mu, float rough
   return table * fresnel_dielectric_cos(mu, 1.5f);
 }
 
-ccl_device_inline float3 metallic_Fss(float3 F0, float3 F90, float falloff)
+ccl_device_inline float3 fresnel_metallic_Fss(float3 F0, float3 B)
 {
-  /* Fss for mix(F0, F90, (1-cosNI)^falloff) */
-  return mix(F0, F90, 2.0f / (sqr(falloff) + 3 * falloff + 2));
+  return saturate(mix(F0, one_float3(), 1.0f / 21.0f) - B * (1.0f / 126.0f));
 }
 
 ccl_device_inline float3 schlick_fresnel_Fss(float3 F0)
 {
-  /* TODO validate using multiGGX code */
-  return (one_float3() + 20.0f * saturate(F0)) * (1.0f / 21.0f);
+  return saturate(mix(F0, one_float3(), 1.0f / 21.0f));
 }
 
 /* TODO Imageworks source */
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index 47ace534440..39ac4161c6e 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -109,6 +109,32 @@ ccl_device float schlick_fresnel(float u)
   return m2 * m2 * m;  // pow(m, 5)
 }
 
+/* Metallic Fresnel term with edge color control.
+ * Based on Schlick Fresnel, but with an optional F82 input that adds the dip at
+ * near-grazing angles that is characteristic for conductors.
+ *
+ * Source:
+ * https://substance3d.adobe.com/documentation/s3d/files/225969599/225969601/1/1647019577092/Adobe+Standard+Material+-+Technical+Documentation.pdf
+ */
+ccl_device float3 metallic_edge_factor(float3 F0, float3 F82)
+{
+  if (F82 == one_float3()) {
+    return zero_float3();
+  }
+
+  /* Precompute the B factor of the F82 model, which scales an additional term around cosI == 1/7. */
+  const float f = 6.0f / 7.0f; /* 1 - cosI_max */
+  const float f5 = sqr(sqr(f)) * f;
+  return (7.0f / (f5 * f)) * mix(F0, one_float3(), f5) * (one_float3() - F82);
+}
+
+ccl_device float3 fresnel_metallic(float3 F0, float3 B, float cosi)
+{
+  float s = saturatef(1.0f - cosi);
+  float s5 = sqr(sqr(s)) * s;
+  return saturate(mix(F0, one_float3(), s5) - B * cosi * s5 * s);
+}
+
 /* Calculate the fresnel color which is a blend between white and the F0 color */
 ccl_device_forceinline float3 interpolate_fresnel_color(float3 L, float3 H, float ior, float3 F0)
 {
diff --git a/intern/cycles/kernel/svm/closure_principled.h b/intern/cycles/kernel/svm/closure_principled.h
index d352cac2fcc..c4a74a4da13 100644
--- a/intern/cycles/kernel/svm/closure_principled.h
+++ b/intern/cycles/kernel/svm/closure_principled.h
@@ -613,9 +613,9 @@ ccl_device_inline float principled_v2_specular(KernelGlobals kg,
     return 0.0f;
   }
 
-  uint falloff_offset, edge_offset, dummy;
+  uint 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(data1, &dummy, &edge_offset, &dummy, &dummy);
   svm_unpack_node_uchar4(data2, &aniso_offset, &rotation_offset, &tangent_offset, &dummy);
 
   /* This function handles two specular components:
@@ -632,6 +632,7 @@ ccl_device_inline float principled_v2_specular(KernelGlobals kg,
     T = stack_load_float3(stack, tangent_offset);
     T = rotate_around_axis(T, N, stack_load_float(stack, rotation_offset) * M_2PI_F);
   }
+  float3 edge_color = stack_load_float3(stack, edge_offset);
 
   ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
       sd, sizeof(MicrofacetBsdf), weight);
@@ -653,8 +654,7 @@ ccl_device_inline float principled_v2_specular(KernelGlobals kg,
   bsdf->alpha_y = sqr(roughness) * aspect;
 
   extra->metal_base = base_color;
-  extra->metal_edge = stack_load_float3(stack, edge_offset);
-  extra->metal_falloff = stack_load_float(stack, falloff_offset);
+  extra->metal_edge_factor = metallic_edge_factor(base_color, edge_color);
 
   float dielectric = (1.0f - metallic) * (1.0f - transmission);
   sd->flag |= bsdf_microfacet_ggx_fresnel_v2_setup(kg, bsdf, sd, metallic, dielectric);
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index f8412a430d1..3a11b9301e2 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -2744,7 +2744,6 @@ NODE_DEFINE(PrincipledBsdfNode)
   SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
   SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
   SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
-  SOCKET_IN_FLOAT(metallic_falloff, "Metallic Falloff", 0.2f);
   SOCKET_IN_COLOR(metallic_edge, "Metallic Edge", make_float3(1.0f, 1.0f, 1.0f));
   SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
   SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.0f);
@@ -2930,7 +2929,7 @@ void PrincipledBsdfNode::compile_v2(SVMCompiler &compiler)
                                     compiler.stack_assign(input("Subsurface Anisotropy")),
                                     compiler.stack_assign(input("Subsurface Radius")),
                                     subsurface_method);
-  uint metallic = compiler.encode_uchar4(compiler.stack_assign(input("Metallic Falloff")),
+  uint metallic = compiler.encode_uchar4(SVM_STACK_INVALID,
                                          compiler.stack_assign(input("Metallic Edge")),
                                          SVM_STACK_INVALID,
                                          distribution);
diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h
index 37823fb199b..bec1a70f4b5 100644
--- a/intern/cycles/scene/shader_nodes.h
+++ b/intern/cycles/scene/shader_nodes.h
@@ -536,7 +536,6 @@ class PrincipledBsdfNode : public BsdfBaseNode {
   NODE_SOCKET_API(float, subsurface_ior)
   NODE_SOCKET_API(float, subsurface_anisotropy)
   NODE_SOCKET_API(float, metallic)
-  NODE_SOCKET_API(float, metallic_falloff)
   NODE_SOCKET_API(float3, metallic_edge)
   NODE_SOCKET_API(float, subsurface)
   NODE_SOCKET_API(float, subsurface_scale)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index 8b4936b6fb3..3e3af51c15a 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -22,7 +22,6 @@ void node_bsdf_principled(vec4 base_color,
                           float subsurface_anisotropy,
                           float metallic,
                           vec4 metallic_edge, //todo
-                          float metallic_falloff, //todo
                           float specular,
                           float specular_tint,
                           float roughness,
diff --git a/source/blender/nodes/shader/nodes/no

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list