[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