[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