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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs