[Bf-blender-cvs] [ea1419ea5ed] principled-v2: Add sheen V2 component
Lukas Stockner
noreply at git.blender.org
Mon Jul 4 23:56:14 CEST 2022
Commit: ea1419ea5edb40291961271ea5d5f0cb01dc62b1
Author: Lukas Stockner
Date: Mon Jul 4 23:31:48 2022 +0200
Branches: principled-v2
https://developer.blender.org/rBea1419ea5edb40291961271ea5d5f0cb01dc62b1
Add sheen V2 component
===================================================================
M intern/cycles/app/cycles_precompute.cpp
M intern/cycles/kernel/closure/bsdf.h
M intern/cycles/kernel/closure/bsdf_microfacet_util.h
M intern/cycles/kernel/closure/bsdf_principled_sheen.h
M intern/cycles/kernel/film/passes.h
M intern/cycles/kernel/svm/closure_principled.h
M intern/cycles/kernel/svm/types.h
M intern/cycles/kernel/tables.h
===================================================================
diff --git a/intern/cycles/app/cycles_precompute.cpp b/intern/cycles/app/cycles_precompute.cpp
index eb5fe2f13f9..5ca0ac0953e 100644
--- a/intern/cycles/app/cycles_precompute.cpp
+++ b/intern/cycles/app/cycles_precompute.cpp
@@ -13,6 +13,7 @@
#include "kernel/closure/bsdf_microfacet.h"
#include "kernel/closure/bsdf_microfacet_glass.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
#include <iostream>
@@ -37,6 +38,35 @@ inline float Sobol2(uint32_t n, uint32_t scramble)
return ((scramble >> 8) & 0xffffff) / float(1 << 24);
}
+static float precompute_sheen_E(float rough, float mu, float u1, float u2)
+{
+ PrincipledSheenBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.roughness = sqr(rough);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_principled_sheen_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ return clamp(average(eval) / pdf, 0.0f, 1e5f);
+ }
+ return 0.0f;
+}
+
static float precompute_ggx_E(float rough, float mu, float u1, float u2)
{
MicrofacetBsdf bsdf;
@@ -144,6 +174,10 @@ bool cycles_precompute(std::string name);
bool cycles_precompute(std::string name)
{
std::map<string, PrecomputeTerm> precompute_terms;
+ precompute_terms["sheen_E"] = {
+ 2, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
+ return precompute_sheen_E(rough, mu, u1, u2);
+ }};
precompute_terms["ggx_E"] = {
2, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2, uint *rng) {
return precompute_ggx_E(rough, mu, u1, u2);
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 3a578b9f06e..ef148f5abb4 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -383,6 +383,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
label = bsdf_principled_sheen_sample(sc,
Ng,
sd->I,
@@ -519,6 +520,7 @@ ccl_device_inline
eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
break;
# endif /* __PRINCIPLED__ */
@@ -599,6 +601,7 @@ ccl_device_inline
eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
break;
# endif /* __PRINCIPLED__ */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
index b355c53aaee..bf6c277bc67 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_util.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -77,7 +77,7 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(
}
/* Albedo correction.
- * TODO: Use proper lookup table code for this data. */
+ * TODO: Use proper lookup table code for this data. Also use 0.5px offset. */
ccl_device_forceinline float microfacet_ggx_glass_E(float mu, float rough, float ior)
{
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
index 3a96a93db73..fa580a540cb 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
@@ -15,6 +15,7 @@ CCL_NAMESPACE_BEGIN
typedef struct PrincipledSheenBsdf {
SHADER_CLOSURE_BASE;
float avg_value;
+ float roughness;
} PrincipledSheenBsdf;
static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledSheenBsdf),
@@ -50,6 +51,76 @@ calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_priv
return make_float3(value, value, value);
}
+/* Based on
+ * https://dassaultsystemes-technology.github.io/EnterprisePBRShadingModel/spec-2022x.md.html#components/sheen.
+ */
+ccl_device_inline float sheen_v2_lambda(float mu, float w)
+{
+ float a = lerp(11.9095f, 13.7000f, w);
+ float b = lerp(4.68753f, 2.92754f, w);
+ float c = lerp(0.33467f, 0.28670f, w);
+ float d = lerp(-2.22664f, -0.81757f, w);
+ float e = lerp(-1.76591f, -1.22466f, w);
+
+ float exponent;
+ if (mu < 0.5f) {
+ exponent = a / (1 + b * powf(mu, c)) + d * mu + e;
+ }
+ else {
+ exponent = 2 * a / (1 + b * exp2(-c)) - a / (1 + b * powf(1 - mu, c)) + d * mu + e;
+ }
+ return expf(exponent);
+}
+
+ccl_device_inline float3 sheen_v2_eval(float3 N, float3 V, float3 L, float3 H, float r, float *pdf)
+{
+ float cosNH = dot(N, H), cosNV = dot(N, V), cosNL = dot(N, L);
+
+ if (cosNH < 0 || cosNV < 0 || cosNL < 0) {
+ return zero_float3();
+ }
+
+ /* Evaluate microfacet distribution. */
+ float sinTheta2 = 1 - sqr(cosNH);
+ float invR = 1 / r;
+ float D = M_1_2PI_F * (2 + invR) * powf(sinTheta2, 0.5f * invR);
+
+ /* Evaluate shadowing-masking terms. */
+ float w = -1.59612f / (1 + 0.20375f * fast_safe_powf(r, -0.55825f)) + 1.32805f;
+ float lambdaV = sheen_v2_lambda(cosNV, w);
+ float lambdaL = sheen_v2_lambda(cosNL, w);
+
+ /* Soften shadow terminator. */
+ lambdaL = fast_safe_powf(lambdaL, 1 + 2 * sqr(sqr(sqr(1 - cosNL))));
+
+ /* Combined microfacet BSDF.
+ * Usual form is F*D*G/(4*cosNL*cosNV), but here we have no Fresnel, we skip dividing by cosNL
+ * since Cycles convention is returning BSDF*cosNL, and we use the combined shadowing-masking
+ * term G=1/(1+lambdaV+lambdaL).
+ */
+ float val = D / (4 * cosNV * (1 + lambdaV + lambdaL));
+ return make_float3(val, val, val);
+}
+
+ccl_device_forceinline float sheen_v2_E(float mu, float rough)
+{
+ /* TODO: Cleanup. */
+ rough = saturatef(1 - sqrtf(rough) - 1.0f / 64.0f) * 32.0f;
+ mu = saturatef(mu - 1.0f / 64.0f) * 32.0f;
+
+ int rough_i = min(31, (int)rough);
+ int rough_i1 = min(31, rough_i + 1);
+ int mu_i = min(31, (int)mu);
+ int mu_i1 = min(31, mu_i + 1);
+
+ rough -= rough_i;
+ mu -= mu_i;
+
+ float a = lerp(table_sheen_E[rough_i][mu_i], table_sheen_E[rough_i][mu_i1], mu);
+ float b = lerp(table_sheen_E[rough_i1][mu_i], table_sheen_E[rough_i1][mu_i1], mu);
+ return lerp(a, b, rough);
+}
+
ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
ccl_private PrincipledSheenBsdf *bsdf)
{
@@ -59,6 +130,20 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
+ccl_device int bsdf_principled_sheen_v2_setup(ccl_private const ShaderData *sd,
+ ccl_private PrincipledSheenBsdf *bsdf)
+{
+ // TODO: Also expose as separate node. Add enum to Velvet BSDF maybe?
+ bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID;
+
+ bsdf->roughness = clamp(bsdf->roughness, 1e-3f, 1.0f);
+
+ bsdf->avg_value = sheen_v2_E(dot(bsdf->N, sd->I), bsdf->roughness);
+ bsdf->sample_weight *= bsdf->avg_value;
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
@@ -73,7 +158,12 @@ ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClo
if (dot(N, omega_in) > 0.0f) {
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- return calculate_principled_sheen_brdf(N, V, L, H, pdf);
+ if (bsdf->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID) {
+ return sheen_v2_eval(N, V, L, H, bsdf->roughness, pdf);
+ }
+ else {
+ return calculate_principled_sheen_brdf(N, V, L, H, pdf);
+ }
}
else {
*pdf = 0.0f;
@@ -112,7 +202,12 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
if (dot(Ng, *omega_in) > 0) {
float3 H = normalize(I + *omega_in);
- *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf);
+ if (bsdf->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID) {
+ *eval = sheen_v2_eval(N, I, *omega_in, H, bsdf->roughness, pdf);
+ }
+ else {
+ *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf);
+ }
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the diffuse bounce
diff --git a/intern/cycles/kernel/film/passes.h b/intern/cycles/kernel/film/passes.h
index 1f5cf2048f1..d6562a32cc4 100644
--- a/intern/cycles/kernel/film/passes.h
+++ b/intern/cycles/kernel/film/passes.h
@@ -72,7 +72,7 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
closure_albedo *= bsdf->extra->fresnel_color;
}
- else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) {
+ else if (CLOSURE_IS_BSDF_SHEEN(sc->type)) {
ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)sc;
closure_albedo *= bsdf->avg_value;
}
diff --git a/intern/cycles/kernel/svm/closure_principled.h b/intern/cycles/kernel/svm/closure_principled.h
index 33476c95f99..9c9e9ebc709 100644
--- a/intern/cycles/kernel/svm/closure_principled.h
+++ b/intern/cycles/kernel/svm/closure_principled.h
@@ -514,6 +514,39 @
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list