[Bf-blender-cvs] [320757bc611] master: Refactor microfacet BSDF to reduce repetition
Weizhen Huang
noreply at git.blender.org
Thu Jan 19 12:08:04 CET 2023
Commit: 320757bc6111bf7c652068368b92312c994838f8
Author: Weizhen Huang
Date: Thu Jan 19 12:06:14 2023 +0100
Branches: master
https://developer.blender.org/rB320757bc6111bf7c652068368b92312c994838f8
Refactor microfacet BSDF to reduce repetition
===================================================================
M intern/cycles/kernel/closure/bsdf_microfacet.h
M intern/cycles/kernel/integrator/mnee.h
===================================================================
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index ed438b1f483..377cf836fb8 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -43,17 +43,18 @@ ccl_device_inline void microfacet_beckmann_sample_slopes(KernelGlobals kg,
ccl_private float *slope_y,
ccl_private float *G1i)
{
- /* special case (normal incidence) */
+ /* Special case (normal incidence). */
if (cos_theta_i >= 0.99999f) {
const float r = sqrtf(-logf(randu));
const float phi = M_2PI_F * randv;
*slope_x = r * cosf(phi);
*slope_y = r * sinf(phi);
*G1i = 1.0f;
+
return;
}
- /* precomputations */
+ /* Precomputations. */
const float tan_theta_i = sin_theta_i / cos_theta_i;
const float inv_a = tan_theta_i;
const float cot_theta_i = 1.0f / tan_theta_i;
@@ -129,7 +130,7 @@ ccl_device_inline void microfacet_ggx_sample_slopes(const float cos_theta_i,
ccl_private float *slope_y,
ccl_private float *G1i)
{
- /* special case (normal incidence) */
+ /* Special case (normal incidence). */
if (cos_theta_i >= 0.99999f) {
const float r = sqrtf(randu / (1.0f - randu));
const float phi = M_2PI_F * randv;
@@ -140,13 +141,13 @@ ccl_device_inline void microfacet_ggx_sample_slopes(const float cos_theta_i,
return;
}
- /* precomputations */
+ /* Precomputations. */
const float tan_theta_i = sin_theta_i / cos_theta_i;
const float G1_inv = 0.5f * (1.0f + safe_sqrtf(1.0f + tan_theta_i * tan_theta_i));
*G1i = 1.0f / G1_inv;
- /* sample slope_x */
+ /* Sample slope_x. */
const float A = 2.0f * randu * G1_inv - 1.0f;
const float AA = A * A;
const float tmp = 1.0f / (AA - 1.0f);
@@ -157,7 +158,7 @@ ccl_device_inline void microfacet_ggx_sample_slopes(const float cos_theta_i,
const float slope_x_2 = B * tmp + D;
*slope_x = (A < 0.0f || slope_x_2 * tan_theta_i > 1.0f) ? slope_x_1 : slope_x_2;
- /* sample slope_y */
+ /* Sample slope_y. */
float S;
if (randv > 0.5f) {
@@ -187,7 +188,7 @@ ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals kg,
float3 wi_ = make_float3(alpha_x * wi.x, alpha_y * wi.y, wi.z);
wi_ = normalize(wi_);
- /* get polar coordinates of wi_ */
+ /* Compute polar coordinates of wi_. */
float costheta_ = 1.0f;
float sintheta_ = 0.0f;
float cosphi_ = 1.0f;
@@ -238,26 +239,85 @@ ccl_device_forceinline Spectrum reflection_color(ccl_private const MicrofacetBsd
float3 H)
{
Spectrum F = one_spectrum();
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
- bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
+
+ bool use_clearcoat = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || use_clearcoat);
+
if (use_fresnel) {
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
}
+ if (use_clearcoat) {
+ F *= 0.25f * bsdf->extra->clearcoat;
+ }
+
return F;
}
-ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
+/* Generalized Trowbridge-Reitz for clearcoat. */
+ccl_device_forceinline float bsdf_clearcoat_D(float alpha2, float cos_NH)
{
- if (alpha >= 1.0f)
+ if (alpha2 >= 1.0f) {
return M_1_PI_F;
- float alpha2 = alpha * alpha;
- float t = 1.0f + (alpha2 - 1.0f) * NdotH * NdotH;
+ }
+
+ const float t = 1.0f + (alpha2 - 1.0f) * cos_NH * cos_NH;
return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
}
+/* Monodirectional shadowing-masking term. */
+template<bool beckmann> ccl_device_inline float bsdf_G1_from_sqr_alpha_tan_n(float sqr_alpha_tan_n)
+{
+ if (!beckmann) { /* GGX. */
+ return 2.0f / (1.0f + sqrtf(1.0f + sqr_alpha_tan_n));
+ }
+
+ const float a = inversesqrtf(sqr_alpha_tan_n);
+ return (a > 1.6f) ? 1.0f : ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
+}
+
+template<bool beckmann> ccl_device_inline float bsdf_G1(float alpha2, float cos_N)
+{
+ return bsdf_G1_from_sqr_alpha_tan_n<beckmann>(alpha2 *
+ fmaxf(1.0f / (cos_N * cos_N) - 1.0f, 0.0f));
+}
+
+template<bool beckmann>
+ccl_device_inline float bsdf_aniso_G1(float alpha_x, float alpha_y, float3 V)
+{
+ return bsdf_G1_from_sqr_alpha_tan_n<beckmann>((sqr(alpha_x * V.x) + sqr(alpha_y * V.y)) /
+ sqr(V.z));
+}
+
+/* Smith's separable shadowing-masking term. */
+template<bool beckmann> ccl_device_inline float bsdf_G(float alpha2, float cos_NI, float cos_NO)
+{
+ return bsdf_G1<beckmann>(alpha2, cos_NI) * bsdf_G1<beckmann>(alpha2, cos_NO);
+}
+
+/* Normal distribution function. */
+template<bool beckmann> ccl_device_inline float bsdf_D(float alpha2, float cos_NH)
+{
+ const float cos_NH2 = sqr(cos_NH);
+
+ return beckmann ? expf((1.0f - 1.0f / cos_NH2) / alpha2) / (M_PI_F * alpha2 * sqr(cos_NH2)) :
+ alpha2 / (M_PI_F * sqr(1.0f + (alpha2 - 1.0f) * cos_NH2));
+}
+
+template<bool beckmann>
+ccl_device_inline float bsdf_aniso_D(float alpha_x, float alpha_y, float3 H)
+{
+ H /= make_float3(alpha_x, alpha_y, 1.0f);
+
+ const float cos_NH2 = sqr(H.z);
+ const float alpha2 = alpha_x * alpha_y;
+
+ return beckmann ? expf(-(sqr(H.x) + sqr(H.y)) / cos_NH2) / (M_PI_F * alpha2 * sqr(cos_NH2)) :
+ M_1_PI_F / (alpha2 * sqr(len_squared(H)));
+}
+
ccl_device_forceinline void bsdf_microfacet_fresnel_color(ccl_private const ShaderData *sd,
ccl_private MicrofacetBsdf *bsdf)
{
@@ -274,6 +334,217 @@ ccl_device_forceinline void bsdf_microfacet_fresnel_color(ccl_private const Shad
bsdf->sample_weight *= average(bsdf->extra->fresnel_color);
}
+template<bool beckmann>
+ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
+ const float3 Ng,
+ const float3 wi,
+ const float3 wo,
+ ccl_private float *pdf)
+{
+ ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
+ const bool m_refractive = (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) ||
+ (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+
+ const float3 N = bsdf->N;
+ const float cos_NI = dot(N, wi);
+ const float cos_NO = dot(N, wo);
+ const float cos_NgO = dot(Ng, wo);
+
+ const float alpha_x = bsdf->alpha_x;
+ const float alpha_y = bsdf->alpha_y;
+
+ if ((cos_NI <= 0) || ((cos_NgO < 0.0f) != m_refractive) || ((cos_NO < 0.0f) != m_refractive) ||
+ (alpha_x * alpha_y <= 1e-7f)) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ /* Compute half vector. */
+ float3 H = m_refractive ? -(bsdf->ior * wo + wi) : (wi + wo);
+ const float inv_len_H = 1.0f / len(H);
+ H *= inv_len_H;
+
+ const float cos_NH = dot(N, H);
+ float D, G1i, G1o;
+
+ /* TODO: add support for anisotropic transmission. */
+ if (alpha_x == alpha_y || m_refractive) { /* Isotropic. */
+ float alpha2 = alpha_x * alpha_y;
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ D = bsdf_clearcoat_D(alpha2, cos_NH);
+
+ /* The masking-shadowing term for clearcoat has a fixed alpha of 0.25
+ * => alpha2 = 0.25 * 0.25 */
+ alpha2 = 0.0625f;
+ }
+ else {
+ D = bsdf_D<beckmann>(alpha2, cos_NH);
+ }
+
+ G1i = bsdf_G1<beckmann>(alpha2, cos_NI);
+ G1o = bsdf_G1<beckmann>(alpha2, cos_NO);
+ }
+ else { /* Anisotropic. */
+ float3 X, Y;
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
+
+ const float3 local_H = make_float3(dot(X, H), dot(Y, H), cos_NH);
+ const float3 local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
+ const float3 local_O = make_float3(dot(X, wo), dot(Y, wo), cos_NO);
+
+ D = bsdf_aniso_D<beckmann>(alpha_x, alpha_y, local_H);
+
+ G1i = bsdf_aniso_G1<beckmann>(alpha_x, alpha_y, local_I);
+ G1o = bsdf_aniso_G1<beckmann>(alpha_x, alpha_y, local_O);
+ }
+
+ const float common = G1i * D / cos_NI *
+ (m_refractive ?
+ sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) :
+ 0.25f);
+
+ *pdf = common;
+
+ const Spectrum F = m_refractive ? one_spectrum() : reflection_color(bsdf, wo, H);
+
+ return F * G1o * common;
+}
+
+template<bool beckmann>
+ccl_device int bsdf_microfacet_sample(KernelGlobals kg,
+ ccl_private const ShaderClosure *sc,
+ float3 Ng,
+ float3 wi,
+ float randu,
+ float randv,
+ ccl_private Spectrum *eval,
+ ccl_private float3 *wo,
+ ccl_private float *pdf,
+ ccl_private float2 *sampled_roughness,
+ ccl_private float *eta)
+{
+ ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
+
+ const float m_eta = bsdf->ior;
+ const bool m_refractive = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) ||
+ (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
+ int label = m_refractive ? LABEL_TRANSMIT : LABEL_REFLECT;
+
+ const float3 N = bsdf->N;
+ const float cos_NI = dot(N, wi);
+ if (cos_NI <= 0) {
+ return label | LABEL_GLOSSY;
+ }
+
+ float3 X, Y;
+ const float alpha_x = bsdf->alpha_x;
+ const float alpha_y = bsdf->alpha_y;
+ if (alpha_x == alpha_y) {
+ make_orthonormals(N, &X, &Y);
+ }
+ else {
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list