[Bf-blender-cvs] [a8869c97646] principled-v2: Implement initial version of iridescence, not on metals yet

Lukas Stockner noreply at git.blender.org
Sun Oct 30 00:17:16 CEST 2022


Commit: a8869c97646b6cc253cd23088f52149de0f87c4b
Author: Lukas Stockner
Date:   Sun Oct 30 00:14:03 2022 +0200
Branches: principled-v2
https://developer.blender.org/rBa8869c97646b6cc253cd23088f52149de0f87c4b

Implement initial version of iridescence, not on metals yet

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

M	intern/cycles/app/cycles_precompute.cpp
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/svm/closure_principled.h
M	intern/cycles/scene/shader_nodes.cpp
M	intern/cycles/scene/shader_nodes.h
M	intern/cycles/util/math_float2.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 35f94d8615d..ee8f95f2e17 100644
--- a/intern/cycles/app/cycles_precompute.cpp
+++ b/intern/cycles/app/cycles_precompute.cpp
@@ -290,7 +290,8 @@ static float precompute_ggx_dielectric_E(float rough, float mu, float eta, float
   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);
+  extra.dielectric = make_spectrum(1.0f + Fms * ((1.0f - E) / E));
+  extra.thin_film_thickness = 0.0f;
 
   float3 omega_in;
   Spectrum eval;
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 64e3ce7ba50..a60f24965d0 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -20,8 +20,10 @@ typedef struct MicrofacetExtra {
 typedef struct MicrofacetExtrav2 {
   /* Metallic fresnel control */
   Spectrum metal_base, metal_edge_factor;
-  Spectrum metallic;
-  float dielectric;
+  /* Albedo scaling */
+  Spectrum metallic, dielectric;
+  /* Thin film controls */
+  float thin_film_thickness, thin_film_ior;
 } MicrofacetExtrav2;
 
 // TODO probably remove this for the final code
@@ -62,9 +64,16 @@ ccl_device_forceinline Spectrum reflection_color(ccl_private const MicrofacetBsd
     Spectrum F = zero_spectrum();
     float cosHL = dot(H, L);
 
-    if (extra->dielectric > 0.0f) {
-      /* Dielectric Fresnel, just basic IOR control. */
-      F += make_spectrum(extra->dielectric * fresnel_dielectric_cos(cosHL, bsdf->ior));
+    if (extra->dielectric != zero_spectrum()) {
+      if (extra->thin_film_thickness == 0.0f) {
+        /* Dielectric Fresnel, just basic IOR control. */
+        F += extra->dielectric * fresnel_dielectric_cos(cosHL, bsdf->ior);
+      }
+      else {
+        F += extra->dielectric *
+             fresnel_dielectric_thin_film(
+                 cosHL, bsdf->ior, extra->thin_film_ior, extra->thin_film_thickness);
+      }
     }
 
     if (extra->metallic != zero_spectrum()) {
@@ -110,19 +119,6 @@ ccl_device_inline Spectrum microfacet_ggx_albedo_scaling(KernelGlobals kg,
   /* TODO: Ensure that increase in weight does not mess up glossy color, albedo etc. passes */
 }
 
-ccl_device_inline float microfacet_ggx_albedo_scaling_float(KernelGlobals kg,
-                                                            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(kg, mu, rough), E_avg = microfacet_ggx_E_avg(kg, 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;
@@ -190,12 +186,11 @@ ccl_device int bsdf_microfacet_ggx_fresnel_v2_setup(KernelGlobals kg,
   }
 
   if (dielectric > 0.0f) {
-    float dielectric_Fss = dielectric_fresnel_Fss(bsdf->ior);
-    extra->dielectric = dielectric *
-                        microfacet_ggx_albedo_scaling_float(kg, bsdf, sd, dielectric_Fss);
+    Spectrum dielectric_Fss = make_spectrum(dielectric_fresnel_Fss(bsdf->ior));  // TODO
+    extra->dielectric = dielectric * microfacet_ggx_albedo_scaling(kg, bsdf, sd, dielectric_Fss);
   }
   else {
-    extra->dielectric = 0.0f;
+    extra->dielectric = zero_spectrum();
   }
 
   bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID;
@@ -230,7 +225,8 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_v2_setup(KernelGlobals kg,
   bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
 
   float Fss = dielectric_fresnel_Fss(bsdf->ior);
-  bsdf->weight *= microfacet_ggx_albedo_scaling_float(kg, bsdf, sd, Fss);
+  /* TODO: Keep non-Spectum version of albedo scaling for performance? */
+  bsdf->weight *= microfacet_ggx_albedo_scaling(kg, bsdf, sd, make_spectrum(Fss));
 
   bsdf_microfacet_fresnel_color(sd, bsdf);
 
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_glass.h b/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
index 3c0ea32447b..68688ffa922 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
@@ -66,6 +66,21 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(KernelGlobals kg,
   return SD_BSDF | SD_BSDF_HAS_EVAL;
 }
 
+ccl_device_inline Spectrum glass_fresnel(ccl_private const MicrofacetBsdf *bsdf,
+                                         float cosTheta,
+                                         float *reflect_pdf)
+{
+  if (bsdf->T.x > 0.0f) {
+    Spectrum F = fresnel_dielectric_thin_film(cosTheta, bsdf->ior, bsdf->T.y, bsdf->T.x);
+    *reflect_pdf = average(F);
+    return F;
+  }
+  else {
+    *reflect_pdf = fresnel_dielectric_cos(cosTheta, bsdf->ior);
+    return make_spectrum(*reflect_pdf);
+  }
+}
+
 ccl_device Spectrum bsdf_microfacet_ggx_glass_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
                                                            const float3 N,
                                                            const float3 I,
@@ -89,11 +104,12 @@ ccl_device Spectrum bsdf_microfacet_ggx_glass_eval_reflect(ccl_private const Mic
 
   float common = D * 0.25f / cosNO;
 
-  float F = fresnel_dielectric_cos(dot(m, I), bsdf->ior);
-  float out = F * common / (1 + lambdaO + lambdaI);
-  *pdf = common / (1 + lambdaO);
+  float reflect_pdf;
+  Spectrum F = glass_fresnel(bsdf, dot(m, I), &reflect_pdf);
+
+  Spectrum eval = F * common / (1 + lambdaO + lambdaI);
+  *pdf = reflect_pdf * common / (1 + lambdaO);
 
-  Spectrum eval = make_spectrum(out);
   if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
     eval *= reflection_color(bsdf, omega_in, m);
   }
@@ -122,8 +138,10 @@ ccl_device Spectrum bsdf_microfacet_ggx_glass_eval_transmit(ccl_private const Mi
   float cosMO = dot(m, I);
   float cosMI = dot(m, omega_in);
 
-  float F = fresnel_dielectric_cos(cosMO, eta);
-  if (F == 1.0f) {
+  float reflect_pdf;
+  Spectrum F = glass_fresnel(bsdf, cosMO, &reflect_pdf);
+
+  if (F == one_spectrum()) {
     /* TIR */
     *pdf = 0.0f;
     return zero_spectrum();
@@ -137,10 +155,9 @@ ccl_device Spectrum bsdf_microfacet_ggx_glass_eval_transmit(ccl_private const Mi
   float Ht2 = dot(ht, ht);
 
   float common = fabsf(cosMI * cosMO) * D * sqr(eta) / (cosNO * Ht2);
-  float out = (1.0f - F) * common / (1 + lambdaO + lambdaI);
-  *pdf = common / (1 + lambdaO);
+  Spectrum eval = (one_spectrum() - F) * common / (1 + lambdaO + lambdaI);
+  *pdf = (1.0f - reflect_pdf) / (1 + lambdaO);
 
-  Spectrum eval = make_spectrum(out);
   if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
     eval *= bsdf->extra->color;
   }
@@ -215,19 +232,30 @@ ccl_device int bsdf_microfacet_ggx_glass_sample(ccl_private const ShaderClosure
 
   float3 R, T;
   bool inside; /* Will never be inside, we already checked cosMO */
-  float fresnel = fresnel_dielectric(bsdf->ior, m, I, &R, &T, &inside);
+  fresnel_dielectric(bsdf->ior, m, I, &R, &T, &inside);
+
+  /* TODO: Avoid recomputing Fresnel here if there's no thin-film?
+   * fresnel_dielectric already does it otherwise. */
+  float reflect_pdf;
+  Spectrum F = glass_fresnel(bsdf, cosMO, &reflect_pdf);
 
   // TODO: Somehow get a properly stratified value here, this causes considerable noise
   float randw = hash_float2_to_float(make_float2(randu, randv));
-  bool do_reflect = randw < fresnel;
+  bool do_reflect = randw < reflect_pdf;
 
   float alpha2 = alpha_x * alpha_y;
   if (alpha2 <= 1e-7f) {
     /* Specular case, just return some high number for MIS */
-    *pdf = 1e6f;
-    *eval = make_float3(1e6f, 1e6f, 1e6f);
-
-    *omega_in = do_reflect ? R : T;
+    if (do_reflect) {
+      *pdf = reflect_pdf * 1e6f;
+      *eval = F * 1e6f;
+      *omega_in = R;
+    }
+    else {
+      *pdf = (1.0f - reflect_pdf) * 1e6f;
+      *eval = (one_spectrum() - F) * 1e6f;
+      *omega_in = T;
+    }
 
     if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
       *eval *= do_reflect ? reflection_color(bsdf, *omega_in, m) : bsdf->extra->color;
@@ -250,8 +278,11 @@ ccl_device int bsdf_microfacet_ggx_glass_sample(ccl_private const ShaderClosure
 
     label = LABEL_REFLECT | LABEL_GLOSSY;
     *omega_in = R;
+    *pdf = reflect_pdf;
+    *eval = F;
 
-    common = fresnel * D * 0.25f / cosNO;
+    /* Compute microfacet common term. */
+    common = D * 0.25f / cosNO;
   }
   else {
     cosNI = dot(N, T);
@@ -262,17 +293,18 @@ ccl_device int bsdf_microfacet_ggx_glass_sample(ccl_private const ShaderClosure
 
     label = LABEL_TRANSMIT | LABEL_GLOSSY;
     *omega_in = T;
+    *pdf = 1.0f - reflect_pdf;
+    *eval = one_spectrum() - F;
 
+    /* Compute microfacet common term. */
     float cosMI = dot(m, *omega_in);
     float Ht2 = sqr(bsdf->ior * cosMI + cosMO);
-
-    common = (1.0f - fresnel) * D * fabsf(cosMI * cosMO) * sqr(bsdf->ior) / (cosNO * Ht2);
+    common = D * fabsf(cosMI * cosMO) * sqr(bsdf->ior) / (cosNO * Ht2);
   }
 
   float lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
-  float out = common / (1 + lambdaO + lambdaI);
-  *pdf = common / (1 + lambdaO);
-  *eval = make_spectrum(out);
+  *eval *= common / (1 + lambdaO + lambdaI);
+  *pdf *= common / (1 + lambdaO);
 
   if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
     *eval *= do_reflect ? reflection_color(bsdf, *omega_in, m) : bsdf->extra->color;
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index 8a0902f054b..733084a3228 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -155,4 +155,88 @@ ccl_device_inline float dielectric_fresnel_Fss(float eta)
   return f;
 }
 
+/* Source 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list