diff options
author | Brecht Van Lommel <brecht@blender.org> | 2022-09-22 21:03:24 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2022-09-27 16:56:28 +0300 |
commit | 6d19da0b2d468f099e0c1f56392ab8a1750d114f (patch) | |
tree | 7309b5ef31d5e42dca4e26e13b74bd6f223cba41 /intern | |
parent | bd249eb4f37e65b2f4b3deef775bb136a2c234d1 (diff) |
Cycles: BSDF eval refactor to remove separate reflection/refraction methods
Simplifies code overall to do it inside the eval function, most of the BSDFs
already compute the dot product.
The refactoring in bsdf_principled_hair_eval() was needed to avoid a HIP
compiler bug. Cause is unclear, just changing the implementation enough
is meant to sidestep it.
Ref T92571, D15286
Diffstat (limited to 'intern')
20 files changed, 680 insertions, 916 deletions
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index d202018be9a..71af68aa80e 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -69,7 +69,11 @@ ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosu * Yining Karl Li and Brent Burley. */ ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I) { - float g = safe_divide(dot(Ng, I), dot(N, I) * dot(Ng, N)); + const float cosNI = dot(N, I); + if (cosNI < 0.0f) { + Ng = -Ng; + } + float g = safe_divide(dot(Ng, I), cosNI * dot(Ng, N)); /* If the incoming light is on the unshadowed side, return full brightness. */ if (g >= 1.0f) { @@ -98,6 +102,12 @@ ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multipl return val; } +ccl_device_inline bool bsdf_is_transmission(ccl_private const ShaderClosure *sc, + const float3 omega_in) +{ + return dot(sc->N, omega_in) < 0.0f; +} + ccl_device_inline int bsdf_sample(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, @@ -264,11 +274,12 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, const float frequency_multiplier = kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset; if (frequency_multiplier > 1.0f) { - *eval *= shift_cos_in(dot(*omega_in, sc->N), frequency_multiplier); + const float cosNI = dot(*omega_in, sc->N); + *eval *= shift_cos_in(cosNI, frequency_multiplier); } if (label & LABEL_DIFFUSE) { if (!isequal(sc->N, sd->N)) { - *eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in); + *eval *= bump_shadowing_term(sd->N, sc->N, *omega_in); } } } @@ -491,7 +502,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg, label = LABEL_TRANSMIT | LABEL_GLOSSY; break; case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: - if (is_transmission) + if (bsdf_is_transmission(sc, omega_in)) label = LABEL_TRANSMIT | LABEL_GLOSSY; else label = LABEL_REFLECT | LABEL_GLOSSY; @@ -531,179 +542,104 @@ ccl_device_inline ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, const float3 omega_in, - const bool is_transmission, ccl_private float *pdf) { Spectrum eval = zero_spectrum(); - if (!is_transmission) { - switch (sc->type) { - case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); - break; + switch (sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + eval = bsdf_diffuse_eval(sc, sd->I, omega_in, pdf); + break; #if defined(__SVM__) || defined(__OSL__) - case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); - break; + case CLOSURE_BSDF_OREN_NAYAR_ID: + eval = bsdf_oren_nayar_eval(sc, sd->I, omega_in, pdf); + break; # ifdef __OSL__ - case CLOSURE_BSDF_PHONG_RAMP_ID: - eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf); - break; + case CLOSURE_BSDF_PHONG_RAMP_ID: + eval = bsdf_phong_ramp_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_DIFFUSE_RAMP_ID: + eval = bsdf_diffuse_ramp_eval(sc, sd->I, omega_in, pdf); + break; # endif - case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_MICROFACET_GGX_ID: - case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_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); - break; - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: - eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state); - break; - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: - eval = bsdf_microfacet_multi_ggx_glass_eval_reflect( - sc, sd->I, omega_in, pdf, &sd->lcg_state); - break; - case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: - case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: - eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_DIFFUSE_TOON_ID: - eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_GLOSSY_TOON_ID: - eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: - eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf); - break; - case CLOSURE_BSDF_HAIR_REFLECTION_ID: - eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: - eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: - eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: - eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf); - break; + case CLOSURE_BSDF_TRANSLUCENT_ID: + eval = bsdf_translucent_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_REFLECTION_ID: + eval = bsdf_reflection_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_REFRACTION_ID: + eval = bsdf_refraction_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_TRANSPARENT_ID: + eval = bsdf_transparent_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + eval = bsdf_microfacet_ggx_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: + eval = bsdf_microfacet_multi_ggx_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state); + break; + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: + eval = bsdf_microfacet_multi_ggx_glass_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state); + break; + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: + eval = bsdf_microfacet_beckmann_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: + eval = bsdf_ashikhmin_shirley_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + eval = bsdf_ashikhmin_velvet_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_DIFFUSE_TOON_ID: + eval = bsdf_diffuse_toon_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_GLOSSY_TOON_ID: + eval = bsdf_glossy_toon_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: + eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf); + break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + eval = bsdf_hair_reflection_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + eval = bsdf_hair_transmission_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: + eval = bsdf_principled_diffuse_eval(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: + eval = bsdf_principled_sheen_eval(sc, sd->I, omega_in, pdf); + break; #endif - default: - break; - } - if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { - if (!isequal(sc->N, sd->N)) { - eval *= bump_shadowing_term(sd->N, sc->N, omega_in); - } - } - /* Shadow terminator offset. */ - const float frequency_multiplier = - kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset; - if (frequency_multiplier > 1.0f) { - eval *= shift_cos_in(dot(omega_in, sc->N), frequency_multiplier); - } + default: + break; } - else { - switch (sc->type) { - case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); - break; -#if defined(__SVM__) || defined(__OSL__) - case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_MICROFACET_GGX_ID: - case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_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); - break; - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: - eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state); - break; - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: - eval = bsdf_microfacet_multi_ggx_glass_eval_transmit( - sc, sd->I, omega_in, pdf, &sd->lcg_state); - break; - case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: - case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: - eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_DIFFUSE_TOON_ID: - eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_GLOSSY_TOON_ID: - eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: - eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf); - break; - case CLOSURE_BSDF_HAIR_REFLECTION_ID: - eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: - eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: - eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: - eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf); - break; -#endif - default: - break; + + if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { + if (!isequal(sc->N, sd->N)) { + eval *= bump_shadowing_term(sd->N, sc->N, omega_in); } - if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { - if (!isequal(sc->N, sd->N)) { - eval *= bump_shadowing_term(-sd->N, sc->N, omega_in); - } + } + + /* Shadow terminator offset. */ + const float frequency_multiplier = + kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset; + if (frequency_multiplier > 1.0f) { + const float cosNI = dot(omega_in, sc->N); + if (cosNI >= 0.0f) { + eval *= shift_cos_in(cosNI, frequency_multiplier); } } + #ifdef WITH_CYCLES_DEBUG kernel_assert(*pdf >= 0.0f); kernel_assert(eval.x >= 0.0f && eval.y >= 0.0f && eval.z >= 0.0f); diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index cfe1ced43f2..14a4094d485 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -39,11 +39,10 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough return 2.0f / (roughness * roughness) - 2.0f; } -ccl_device_forceinline Spectrum -bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; float3 N = bsdf->N; @@ -53,70 +52,60 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc, float out = 0.0f; - if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) { + if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f || !(NdotI > 0.0f && NdotO > 0.0f)) { *pdf = 0.0f; return zero_spectrum(); } - if (NdotI > 0.0f && NdotO > 0.0f) { - NdotI = fmaxf(NdotI, 1e-6f); - NdotO = fmaxf(NdotO, 1e-6f); - float3 H = normalize(omega_in + I); - float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f); - float HdotN = fmaxf(dot(H, N), 1e-6f); - - /* pump from original paper - * (first derivative disc., but cancels the HdotI in the pdf nicely) */ - float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI))); - /* pump from d-brdf paper */ - /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ - - float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x); - float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y); - - if (n_x == n_y) { - /* isotropic */ - float e = n_x; - float lobe = powf(HdotN, e); - float norm = (n_x + 1.0f) / (8.0f * M_PI_F); - - out = NdotO * norm * lobe * pump; - /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */ - *pdf = norm * lobe / HdotI; + + NdotI = fmaxf(NdotI, 1e-6f); + NdotO = fmaxf(NdotO, 1e-6f); + float3 H = normalize(omega_in + I); + float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f); + float HdotN = fmaxf(dot(H, N), 1e-6f); + + /* pump from original paper + * (first derivative disc., but cancels the HdotI in the pdf nicely) */ + float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI))); + /* pump from d-brdf paper */ + /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ + + float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x); + float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y); + + if (n_x == n_y) { + /* isotropic */ + float e = n_x; + float lobe = powf(HdotN, e); + float norm = (n_x + 1.0f) / (8.0f * M_PI_F); + + out = NdotO * norm * lobe * pump; + /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */ + *pdf = norm * lobe / HdotI; + } + else { + /* anisotropic */ + float3 X, Y; + make_orthonormals_tangent(N, bsdf->T, &X, &Y); + + float HdotX = dot(H, X); + float HdotY = dot(H, Y); + float lobe; + if (HdotN < 1.0f) { + float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN); + lobe = powf(HdotN, e); } else { - /* anisotropic */ - float3 X, Y; - make_orthonormals_tangent(N, bsdf->T, &X, &Y); - - float HdotX = dot(H, X); - float HdotY = dot(H, Y); - float lobe; - if (HdotN < 1.0f) { - float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN); - lobe = powf(HdotN, e); - } - else { - lobe = 1.0f; - } - float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F); - - out = NdotO * norm * lobe * pump; - *pdf = norm * lobe / HdotI; + lobe = 1.0f; } + float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F); + + out = NdotO * norm * lobe * pump; + *pdf = norm * lobe / HdotI; } return make_spectrum(out); } -ccl_device Spectrum bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, float n_y, float randu, @@ -146,81 +135,84 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc int label = LABEL_REFLECT | LABEL_GLOSSY; float NdotI = dot(N, I); - if (NdotI > 0.0f) { + if (!(NdotI > 0.0f)) { + *pdf = 0.0f; + *eval = zero_spectrum(); + return LABEL_NONE; + } - float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x); - float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y); + float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x); + float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y); - /* get x,y basis on the surface for anisotropy */ - float3 X, Y; + /* get x,y basis on the surface for anisotropy */ + float3 X, Y; + + if (n_x == n_y) + make_orthonormals(N, &X, &Y); + else + make_orthonormals_tangent(N, bsdf->T, &X, &Y); - if (n_x == n_y) - make_orthonormals(N, &X, &Y); - else - make_orthonormals_tangent(N, bsdf->T, &X, &Y); - - /* sample spherical coords for h in tangent space */ - float phi; - float cos_theta; - if (n_x == n_y) { - /* isotropic sampling */ - phi = M_2PI_F * randu; - cos_theta = powf(randv, 1.0f / (n_x + 1.0f)); + /* sample spherical coords for h in tangent space */ + float phi; + float cos_theta; + if (n_x == n_y) { + /* isotropic sampling */ + phi = M_2PI_F * randu; + cos_theta = powf(randv, 1.0f / (n_x + 1.0f)); + } + else { + /* anisotropic sampling */ + if (randu < 0.25f) { /* first quadrant */ + float remapped_randu = 4.0f * randu; + bsdf_ashikhmin_shirley_sample_first_quadrant( + n_x, n_y, remapped_randu, randv, &phi, &cos_theta); } - else { - /* anisotropic sampling */ - if (randu < 0.25f) { /* first quadrant */ - float remapped_randu = 4.0f * randu; - bsdf_ashikhmin_shirley_sample_first_quadrant( - n_x, n_y, remapped_randu, randv, &phi, &cos_theta); - } - else if (randu < 0.5f) { /* second quadrant */ - float remapped_randu = 4.0f * (.5f - randu); - bsdf_ashikhmin_shirley_sample_first_quadrant( - n_x, n_y, remapped_randu, randv, &phi, &cos_theta); - phi = M_PI_F - phi; - } - else if (randu < 0.75f) { /* third quadrant */ - float remapped_randu = 4.0f * (randu - 0.5f); - bsdf_ashikhmin_shirley_sample_first_quadrant( - n_x, n_y, remapped_randu, randv, &phi, &cos_theta); - phi = M_PI_F + phi; - } - else { /* fourth quadrant */ - float remapped_randu = 4.0f * (1.0f - randu); - bsdf_ashikhmin_shirley_sample_first_quadrant( - n_x, n_y, remapped_randu, randv, &phi, &cos_theta); - phi = 2.0f * M_PI_F - phi; - } + else if (randu < 0.5f) { /* second quadrant */ + float remapped_randu = 4.0f * (.5f - randu); + bsdf_ashikhmin_shirley_sample_first_quadrant( + n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + phi = M_PI_F - phi; } - - /* get half vector in tangent space */ - float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta)); - float cos_phi = cosf(phi); - float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */ - float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta); - - /* half vector to world space */ - float3 H = h.x * X + h.y * Y + h.z * N; - float HdotI = dot(H, I); - if (HdotI < 0.0f) - H = -H; - - /* reflect I on H to get omega_in */ - *omega_in = -I + (2.0f * HdotI) * H; - - if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) { - /* Some high number for MIS. */ - *pdf = 1e6f; - *eval = make_spectrum(1e6f); - label = LABEL_REFLECT | LABEL_SINGULAR; + else if (randu < 0.75f) { /* third quadrant */ + float remapped_randu = 4.0f * (randu - 0.5f); + bsdf_ashikhmin_shirley_sample_first_quadrant( + n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + phi = M_PI_F + phi; } - else { - /* leave the rest to eval_reflect */ - *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf); + else { /* fourth quadrant */ + float remapped_randu = 4.0f * (1.0f - randu); + bsdf_ashikhmin_shirley_sample_first_quadrant( + n_x, n_y, remapped_randu, randv, &phi, &cos_theta); + phi = 2.0f * M_PI_F - phi; } } + /* get half vector in tangent space */ + float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta)); + float cos_phi = cosf(phi); + float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */ + float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta); + + /* half vector to world space */ + float3 H = h.x * X + h.y * Y + h.z * N; + float HdotI = dot(H, I); + if (HdotI < 0.0f) + H = -H; + + /* reflect I on H to get omega_in */ + *omega_in = -I + (2.0f * HdotI) * H; + + if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) { + /* Some high number for MIS. */ + *pdf = 1e6f; + *eval = make_spectrum(1e6f); + label = LABEL_REFLECT | LABEL_SINGULAR; + } + else { + /* leave the rest to eval */ + *eval = bsdf_ashikhmin_shirley_eval(sc, I, *omega_in, pdf); + } + return label; } diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 9e68ea5d5e5..ac2183e0848 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -31,10 +31,10 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_ashikhmin_velvet_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc; float m_invsigma2 = bsdf->invsigma2; @@ -42,46 +42,37 @@ ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderC float cosNO = dot(N, I); float cosNI = dot(N, omega_in); - if (cosNO > 0 && cosNI > 0) { - float3 H = normalize(omega_in + I); + if (!(cosNO > 0 && cosNI > 0)) { + *pdf = 0.0f; + return zero_spectrum(); + } - float cosNH = dot(N, H); - float cosHO = fabsf(dot(I, H)); + float3 H = normalize(omega_in + I); - if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) { - *pdf = 0.0f; - return zero_spectrum(); - } - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f); + float cosNH = dot(N, H); + float cosHO = fabsf(dot(I, H)); - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); + if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) { + *pdf = 0.0f; + return zero_spectrum(); + } + float cosNHdivHO = cosNH / cosHO; + cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f); - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; + float fac1 = 2 * fabsf(cosNHdivHO * cosNO); + float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4; - float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically + float sinNH2 = 1 - cosNH * cosNH; + float sinNH4 = sinNH2 * sinNH2; + float cotangent2 = (cosNH * cosNH) / sinNH2; - float out = 0.25f * (D * G) / cosNO; + float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4; + float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically - *pdf = 0.5f * M_1_PI_F; - return make_spectrum(out); - } + float out = 0.25f * (D * G) / cosNO; - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); + *pdf = 0.5f * M_1_PI_F; + return make_spectrum(out); } ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, @@ -101,41 +92,42 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, // distribution over the hemisphere sample_uniform_hemisphere(N, randu, randv, omega_in, pdf); - if (dot(Ng, *omega_in) > 0) { - float3 H = normalize(*omega_in + I); + if (!(dot(Ng, *omega_in) > 0)) { + *pdf = 0.0f; + *eval = zero_spectrum(); + return LABEL_NONE; + } + + float3 H = normalize(*omega_in + I); - float cosNI = dot(N, *omega_in); - float cosNO = dot(N, I); - float cosNH = dot(N, H); - float cosHO = fabsf(dot(I, H)); + float cosNI = dot(N, *omega_in); + float cosNO = dot(N, I); + float cosNH = dot(N, H); + float cosHO = fabsf(dot(I, H)); - if (fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f) { - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f); + if (!(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) { + *pdf = 0.0f; + *eval = zero_spectrum(); + return LABEL_NONE; + } - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); + float cosNHdivHO = cosNH / cosHO; + cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f); - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; + float fac1 = 2 * fabsf(cosNHdivHO * cosNO); + float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4; - float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically + float sinNH2 = 1 - cosNH * cosNH; + float sinNH4 = sinNH2 * sinNH2; + float cotangent2 = (cosNH * cosNH) / sinNH2; - float power = 0.25f * (D * G) / cosNO; + float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4; + float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically + + float power = 0.25f * (D * G) / cosNO; + + *eval = make_spectrum(power); - *eval = make_spectrum(power); - } - else { - *pdf = 0.0f; - *eval = zero_spectrum(); - } - } - else { - *pdf = 0.0f; - *eval = zero_spectrum(); - } return LABEL_REFLECT | LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index ec64c375666..c9c26754651 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -26,10 +26,10 @@ ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; float3 N = bsdf->N; @@ -39,15 +39,6 @@ ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *s return make_spectrum(cos_pi); } -ccl_device Spectrum bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, @@ -81,19 +72,10 @@ ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_translucent_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; float3 N = bsdf->N; diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h index d7faf5c9e9a..e955ed00b92 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h @@ -47,25 +47,23 @@ ccl_device void bsdf_diffuse_ramp_blur(ccl_private ShaderClosure *sc, float roug { } -ccl_device Spectrum bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_ramp_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc; float3 N = bsdf->N; float cos_pi = fmaxf(dot(N, omega_in), 0.0f); - *pdf = cos_pi * M_1_PI_F; - return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F); -} - -ccl_device Spectrum bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - return zero_spectrum(); + if (cos_pi >= 0.0f) { + *pdf = cos_pi * M_1_PI_F; + return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F); + } + else { + *pdf = 0.0f; + return zero_spectrum(); + } } ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc, diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h index 69c05813982..a8ba4044758 100644 --- a/intern/cycles/kernel/closure/bsdf_hair.h +++ b/intern/cycles/kernel/closure/bsdf_hair.h @@ -37,12 +37,17 @@ ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_hair_reflection_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc; + if (dot(bsdf->N, omega_in) < 0.0f) { + *pdf = 0.0f; + return zero_spectrum(); + } + float offset = bsdf->offset; float3 Tg = bsdf->T; float roughness1 = bsdf->roughness1; @@ -84,30 +89,17 @@ ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderCl return make_spectrum(*pdf); } -ccl_device Spectrum bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_hair_transmission_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc; + if (dot(bsdf->N, omega_in) >= 0.0f) { + *pdf = 0.0f; + return zero_spectrum(); + } + float offset = bsdf->offset; float3 Tg = bsdf->T; float roughness1 = bsdf->roughness1; diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h index d0a44c65d52..857b3fbf3a6 100644 --- a/intern/cycles/kernel/closure/bsdf_hair_principled.h +++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h @@ -56,13 +56,7 @@ ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t) /* Remaps the given angle to [-pi, pi]. */ ccl_device_inline float wrap_angle(float a) { - while (a > M_PI_F) { - a -= M_2PI_F; - } - while (a < -M_PI_F) { - a += M_2PI_F; - } - return a; + return (a + M_PI_F) - M_2PI_F * floorf((a + M_PI_F) / M_2PI_F) - M_PI_F; } /* Logistic distribution function. */ @@ -271,76 +265,72 @@ ccl_device Spectrum bsdf_principled_hair_eval(KernelGlobals kg, kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length)); ccl_private const PrincipledHairBSDF *bsdf = (ccl_private const PrincipledHairBSDF *)sc; - float3 Y = float4_to_float3(bsdf->extra->geom); + const float3 Y = float4_to_float3(bsdf->extra->geom); - float3 X = safe_normalize(sd->dPdu); + const float3 X = safe_normalize(sd->dPdu); kernel_assert(fabsf(dot(X, Y)) < 1e-3f); - float3 Z = safe_normalize(cross(X, Y)); + const float3 Z = safe_normalize(cross(X, Y)); - float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z)); - float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z)); + const float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z)); + const float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z)); - float sin_theta_o = wo.x; - float cos_theta_o = cos_from_sin(sin_theta_o); - float phi_o = atan2f(wo.z, wo.y); + const float sin_theta_o = wo.x; + const float cos_theta_o = cos_from_sin(sin_theta_o); + const float phi_o = atan2f(wo.z, wo.y); - float sin_theta_t = sin_theta_o / bsdf->eta; - float cos_theta_t = cos_from_sin(sin_theta_t); + const float sin_theta_t = sin_theta_o / bsdf->eta; + const float cos_theta_t = cos_from_sin(sin_theta_t); - float sin_gamma_o = bsdf->extra->geom.w; - float cos_gamma_o = cos_from_sin(sin_gamma_o); - float gamma_o = safe_asinf(sin_gamma_o); + const float sin_gamma_o = bsdf->extra->geom.w; + const float cos_gamma_o = cos_from_sin(sin_gamma_o); + const float gamma_o = safe_asinf(sin_gamma_o); - float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o)); - float cos_gamma_t = cos_from_sin(sin_gamma_t); - float gamma_t = safe_asinf(sin_gamma_t); + const float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o)); + const float cos_gamma_t = cos_from_sin(sin_gamma_t); + const float gamma_t = safe_asinf(sin_gamma_t); - Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); + const Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); Spectrum Ap[4]; float Ap_energy[4]; hair_attenuation( kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy); - float sin_theta_i = wi.x; - float cos_theta_i = cos_from_sin(sin_theta_i); - float phi_i = atan2f(wi.z, wi.y); + const float sin_theta_i = wi.x; + const float cos_theta_i = cos_from_sin(sin_theta_i); + const float phi_i = atan2f(wi.z, wi.y); - float phi = phi_i - phi_o; + const float phi = phi_i - phi_o; float angles[6]; hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles); - Spectrum F; - float F_energy; - float Mp, Np; - - /* Primary specular (R). */ - Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness); - Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t); - F = Ap[0] * Mp * Np; - F_energy = Ap_energy[0] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); - - /* Transmission (TT). */ - Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v); - Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t); - F += Ap[1] * Mp * Np; - F_energy += Ap_energy[1] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); - - /* Secondary specular (TRT). */ - Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v); - Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t); - F += Ap[2] * Mp * Np; - F_energy += Ap_energy[2] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + Spectrum F = zero_spectrum(); + float F_energy = 0.0f; + + /* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */ + for (int i = 0; i < 3; i++) { + const float Mp = longitudinal_scattering(angles[2 * i], + angles[2 * i + 1], + sin_theta_o, + cos_theta_o, + (i == 0) ? bsdf->m0_roughness : + (i == 1) ? 0.25f * bsdf->v : + 4.0f * bsdf->v); + const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t); + F += Ap[i] * Mp * Np; + F_energy += Ap_energy[i] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + } /* Residual component (TRRT+). */ - Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v); - Np = M_1_2PI_F; - F += Ap[3] * Mp * Np; - F_energy += Ap_energy[3] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + { + const float Mp = longitudinal_scattering( + sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v); + const float Np = M_1_2PI_F; + F += Ap[3] * Mp * Np; + F_energy += Ap_energy[3] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + } *pdf = F_energy; return F; @@ -363,35 +353,35 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, *sampled_roughness = make_float2(bsdf->m0_roughness, bsdf->m0_roughness); *eta = bsdf->eta; - float3 Y = float4_to_float3(bsdf->extra->geom); + const float3 Y = float4_to_float3(bsdf->extra->geom); - float3 X = safe_normalize(sd->dPdu); + const float3 X = safe_normalize(sd->dPdu); kernel_assert(fabsf(dot(X, Y)) < 1e-3f); - float3 Z = safe_normalize(cross(X, Y)); + const float3 Z = safe_normalize(cross(X, Y)); - float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z)); + const float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z)); float2 u[2]; u[0] = make_float2(randu, randv); u[1].x = lcg_step_float(&sd->lcg_state); u[1].y = lcg_step_float(&sd->lcg_state); - float sin_theta_o = wo.x; - float cos_theta_o = cos_from_sin(sin_theta_o); - float phi_o = atan2f(wo.z, wo.y); + const float sin_theta_o = wo.x; + const float cos_theta_o = cos_from_sin(sin_theta_o); + const float phi_o = atan2f(wo.z, wo.y); - float sin_theta_t = sin_theta_o / bsdf->eta; - float cos_theta_t = cos_from_sin(sin_theta_t); + const float sin_theta_t = sin_theta_o / bsdf->eta; + const float cos_theta_t = cos_from_sin(sin_theta_t); - float sin_gamma_o = bsdf->extra->geom.w; - float cos_gamma_o = cos_from_sin(sin_gamma_o); - float gamma_o = safe_asinf(sin_gamma_o); + const float sin_gamma_o = bsdf->extra->geom.w; + const float cos_gamma_o = cos_from_sin(sin_gamma_o); + const float gamma_o = safe_asinf(sin_gamma_o); - float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o)); - float cos_gamma_t = cos_from_sin(sin_gamma_t); - float gamma_t = safe_asinf(sin_gamma_t); + const float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o)); + const float cos_gamma_t = cos_from_sin(sin_gamma_t); + const float gamma_t = safe_asinf(sin_gamma_t); - Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); + const Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); Spectrum Ap[4]; float Ap_energy[4]; hair_attenuation( @@ -414,7 +404,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, } u[1].x = max(u[1].x, 1e-5f); - float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v)); + const float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v)); float sin_theta_i = -fac * sin_theta_o + cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o; float cos_theta_i = cos_from_sin(sin_theta_i); @@ -433,41 +423,37 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, else { phi = M_2PI_F * u[0].y; } - float phi_i = phi_o + phi; + const float phi_i = phi_o + phi; hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles); - Spectrum F; - float F_energy; - float Mp, Np; - - /* Primary specular (R). */ - Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness); - Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t); - F = Ap[0] * Mp * Np; - F_energy = Ap_energy[0] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); - - /* Transmission (TT). */ - Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v); - Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t); - F += Ap[1] * Mp * Np; - F_energy += Ap_energy[1] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); - - /* Secondary specular (TRT). */ - Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v); - Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t); - F += Ap[2] * Mp * Np; - F_energy += Ap_energy[2] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + Spectrum F = zero_spectrum(); + float F_energy = 0.0f; + + /* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */ + for (int i = 0; i < 3; i++) { + const float Mp = longitudinal_scattering(angles[2 * i], + angles[2 * i + 1], + sin_theta_o, + cos_theta_o, + (i == 0) ? bsdf->m0_roughness : + (i == 1) ? 0.25f * bsdf->v : + 4.0f * bsdf->v); + const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t); + F += Ap[i] * Mp * Np; + F_energy += Ap_energy[i] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + } /* Residual component (TRRT+). */ - Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v); - Np = M_1_2PI_F; - F += Ap[3] * Mp * Np; - F_energy += Ap_energy[3] * Mp * Np; - kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + { + const float Mp = longitudinal_scattering( + sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v); + const float Np = M_1_2PI_F; + F += Ap[3] * Mp * Np; + F_energy += Ap_energy[3] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); + } *eval = F; *pdf = F_energy; diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index f29897bc55d..4eb7cd5df22 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -357,146 +357,129 @@ ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float ro bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y); } -ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 N = bsdf->N; - - if (m_refractive || alpha_x * alpha_y <= 1e-7f) { + if (!(cosNI > 0 && cosNO > 0)) { *pdf = 0.0f; return zero_spectrum(); } - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - - if (cosNI > 0 && cosNO > 0) { - /* get half vector */ - float3 m = normalize(omega_in + I); - float alpha2 = alpha_x * alpha_y; - float D, G1o, G1i; - - if (alpha_x == alpha_y) { - /* isotropic - * eq. 20: (F*G*D)/(4*in*on) - * eq. 33: first we calculate D(m) */ - float cosThetaM = dot(N, m); - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - - if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { - /* use GTR1 for clearcoat */ - D = D_GTR1(cosThetaM, bsdf->alpha_x); - - /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */ - alpha2 = 0.0625f; - } - else { - /* use GTR2 otherwise */ - D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - } + /* get half vector */ + float3 m = normalize(omega_in + I); + float alpha2 = alpha_x * alpha_y; + float D, G1o, G1i; + + if (alpha_x == alpha_y) { + /* isotropic + * eq. 20: (F*G*D)/(4*in*on) + * eq. 33: first we calculate D(m) */ + float cosThetaM = dot(N, m); + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - /* eq. 34: now calculate G1(i,m) and G1(o,m) */ - G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + /* use GTR1 for clearcoat */ + D = D_GTR1(cosThetaM, bsdf->alpha_x); + + /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */ + alpha2 = 0.0625f; } else { - /* anisotropic */ - float3 X, Y, Z = N; - make_orthonormals_tangent(Z, bsdf->T, &X, &Y); + /* use GTR2 otherwise */ + D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + } - /* distribution */ - float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); - float slope_x = -local_m.x / (local_m.z * alpha_x); - float slope_y = -local_m.y / (local_m.z * alpha_y); - float slope_len = 1 + slope_x * slope_x + slope_y * slope_y; + /* eq. 34: now calculate G1(i,m) and G1(o,m) */ + G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + } + else { + /* anisotropic */ + float3 X, Y, Z = N; + make_orthonormals_tangent(Z, bsdf->T, &X, &Y); - float cosThetaM = local_m.z; - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; + /* distribution */ + float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); + float slope_x = -local_m.x / (local_m.z * alpha_x); + float slope_y = -local_m.y / (local_m.z * alpha_y); + float slope_len = 1 + slope_x * slope_x + slope_y * slope_y; - D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4); + float cosThetaM = local_m.z; + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; - /* G1(i,m) and G1(o,m) */ - float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO); - float cosPhiO = dot(I, X); - float sinPhiO = dot(I, Y); + D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4); - float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) + - (sinPhiO * sinPhiO) * (alpha_y * alpha_y); - alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO; + /* G1(i,m) and G1(o,m) */ + float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO); + float cosPhiO = dot(I, X); + float sinPhiO = dot(I, Y); - G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2)); + float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) + + (sinPhiO * sinPhiO) * (alpha_y * alpha_y); + alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO; - float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI); - float cosPhiI = dot(omega_in, X); - float sinPhiI = dot(omega_in, Y); + G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2)); - float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) + - (sinPhiI * sinPhiI) * (alpha_y * alpha_y); - alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI; + float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI); + float cosPhiI = dot(omega_in, X); + float sinPhiI = dot(omega_in, Y); - G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2)); - } + float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) + + (sinPhiI * sinPhiI) * (alpha_y * alpha_y); + alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI; - float G = G1o * G1i; + G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2)); + } - /* eq. 20 */ - float common = D * 0.25f / cosNO; + float G = G1o * G1i; - Spectrum F = reflection_color(bsdf, omega_in, m); - if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { - F *= 0.25f * bsdf->extra->clearcoat; - } + /* eq. 20 */ + float common = D * 0.25f / cosNO; - Spectrum out = F * G * common; + Spectrum F = reflection_color(bsdf, omega_in, m); + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + F *= 0.25f * bsdf->extra->clearcoat; + } - /* eq. 2 in distribution of visible normals sampling - * `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */ + Spectrum out = F * G * common; - /* eq. 38 - but see also: - * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - * `pdf = pm * 0.25 / dot(m, I);` */ - *pdf = G1o * common; + /* eq. 2 in distribution of visible normals sampling + * `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */ - return out; - } + /* eq. 38 - but see also: + * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + * `pdf = pm * 0.25 / dot(m, I);` */ + *pdf = G1o * common; - return zero_spectrum(); + return out; } -ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - float m_eta = bsdf->ior; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 N = bsdf->N; - - if (!m_refractive || alpha_x * alpha_y <= 1e-7f) { - *pdf = 0.0f; - return zero_spectrum(); - } - - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - if (cosNO <= 0 || cosNI >= 0) { *pdf = 0.0f; return zero_spectrum(); /* vectors on same side -- not possible */ } /* compute half-vector of the refraction (eq. 16) */ + float m_eta = bsdf->ior; float3 ht = -(m_eta * omega_in + I); float3 Ht = normalize(ht); float cosHO = dot(Ht, I); @@ -533,6 +516,30 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderCl return make_spectrum(out); } +ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) +{ + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + const float alpha_x = bsdf->alpha_x; + const float alpha_y = bsdf->alpha_y; + const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; + const float3 N = bsdf->N; + const float cosNO = dot(N, I); + const float cosNI = dot(N, omega_in); + + if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) { + *pdf = 0.0f; + return zero_spectrum(); + } + + return (cosNI < 0.0f) ? bsdf_microfacet_ggx_eval_transmit( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) : + bsdf_microfacet_ggx_eval_reflect( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI); +} + ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, @@ -811,111 +818,95 @@ ccl_device_inline float bsdf_beckmann_aniso_G1( return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f); } -ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 N = bsdf->N; - - if (m_refractive || alpha_x * alpha_y <= 1e-7f) { + if (!(cosNO > 0 && cosNI > 0)) { *pdf = 0.0f; return zero_spectrum(); } - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - - if (cosNO > 0 && cosNI > 0) { - /* get half vector */ - float3 m = normalize(omega_in + I); - - float alpha2 = alpha_x * alpha_y; - float D, G1o, G1i; - - if (alpha_x == alpha_y) { - /* isotropic - * eq. 20: (F*G*D)/(4*in*on) - * eq. 25: first we calculate D(m) */ - float cosThetaM = dot(N, m); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); - - /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */ - G1o = bsdf_beckmann_G1(alpha_x, cosNO); - G1i = bsdf_beckmann_G1(alpha_x, cosNI); - } - else { - /* anisotropic */ - float3 X, Y, Z = N; - make_orthonormals_tangent(Z, bsdf->T, &X, &Y); + /* get half vector */ + float3 m = normalize(omega_in + I); - /* distribution */ - float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); - float slope_x = -local_m.x / (local_m.z * alpha_x); - float slope_y = -local_m.y / (local_m.z * alpha_y); + float alpha2 = alpha_x * alpha_y; + float D, G1o, G1i; - float cosThetaM = local_m.z; - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; + if (alpha_x == alpha_y) { + /* isotropic + * eq. 20: (F*G*D)/(4*in*on) + * eq. 25: first we calculate D(m) */ + float cosThetaM = dot(N, m); + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); + + /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */ + G1o = bsdf_beckmann_G1(alpha_x, cosNO); + G1i = bsdf_beckmann_G1(alpha_x, cosNI); + } + else { + /* anisotropic */ + float3 X, Y, Z = N; + make_orthonormals_tangent(Z, bsdf->T, &X, &Y); - D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4); + /* distribution */ + float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m)); + float slope_x = -local_m.x / (local_m.z * alpha_x); + float slope_y = -local_m.y / (local_m.z * alpha_y); - /* G1(i,m) and G1(o,m) */ - G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y)); - G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y)); - } + float cosThetaM = local_m.z; + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; - float G = G1o * G1i; + D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4); - /* eq. 20 */ - float common = D * 0.25f / cosNO; - float out = G * common; + /* G1(i,m) and G1(o,m) */ + G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y)); + G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y)); + } - /* eq. 2 in distribution of visible normals sampling - * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */ + float G = G1o * G1i; - /* eq. 38 - but see also: - * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - * pdf = pm * 0.25 / dot(m, I); */ - *pdf = G1o * common; + /* eq. 20 */ + float common = D * 0.25f / cosNO; + float out = G * common; - return make_spectrum(out); - } + /* eq. 2 in distribution of visible normals sampling + * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */ + + /* eq. 38 - but see also: + * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + * pdf = pm * 0.25 / dot(m, I); */ + *pdf = G1o * common; - return zero_spectrum(); + return make_spectrum(out); } -ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc, +ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const MicrofacetBsdf *bsdf, + const float3 N, const float3 I, const float3 omega_in, - ccl_private float *pdf) + ccl_private float *pdf, + const float alpha_x, + const float alpha_y, + const float cosNO, + const float cosNI) { - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - float alpha_x = bsdf->alpha_x; - float alpha_y = bsdf->alpha_y; - float m_eta = bsdf->ior; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 N = bsdf->N; - - if (!m_refractive || alpha_x * alpha_y <= 1e-7f) { - *pdf = 0.0f; - return zero_spectrum(); - } - - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - if (cosNO <= 0 || cosNI >= 0) { *pdf = 0.0f; return zero_spectrum(); } + + const float m_eta = bsdf->ior; /* compute half-vector of the refraction (eq. 16) */ float3 ht = -(m_eta * omega_in + I); float3 Ht = normalize(ht); @@ -950,6 +941,30 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const Sha return make_spectrum(out); } +ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) +{ + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + const float alpha_x = bsdf->alpha_x; + const float alpha_y = bsdf->alpha_y; + const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; + const float3 N = bsdf->N; + const float cosNO = dot(N, I); + const float cosNI = dot(N, omega_in); + + if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) { + *pdf = 0.0f; + return zero_spectrum(); + } + + return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) : + bsdf_microfacet_beckmann_eval_reflect( + bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI); +} + ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index 34115749611..73cc0d292a1 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -415,21 +415,11 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet return bsdf_microfacet_multi_ggx_common_setup(bsdf); } -ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) +ccl_device Spectrum bsdf_microfacet_multi_ggx_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf, + ccl_private uint *lcg_state) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; @@ -588,12 +578,11 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } -ccl_device Spectrum -bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) +ccl_device Spectrum bsdf_microfacet_multi_ggx_glass_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf, + ccl_private uint *lcg_state) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; @@ -609,55 +598,22 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z)); float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z)); - *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior); - kernel_assert(*pdf >= 0.f); - return mf_eval_glass(localI, - localO, - false, - bsdf->extra->color, - bsdf->alpha_x, - bsdf->alpha_y, - lcg_state, - bsdf->ior, - false, - bsdf->extra->color); -} - -ccl_device Spectrum -bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) -{ - ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - - if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) { - *pdf = 0.0f; - return zero_spectrum(); - } - - bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID); - - float3 X, Y, Z; - Z = bsdf->N; - make_orthonormals(Z, &X, &Y); - - float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z)); - float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z)); + const bool is_transmission = localO.z < 0.0f; + const bool use_fresnel = !is_transmission && + (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID); *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior); kernel_assert(*pdf >= 0.f); return mf_eval_glass(localI, localO, - true, + !is_transmission, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, - bsdf->extra->cspec0); + (is_transmission) ? bsdf->extra->color : bsdf->extra->cspec0); } ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg, diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h index b85390f0676..6912d5b3f18 100644 --- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -47,10 +47,10 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_oren_nayar_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc; if (dot(bsdf->N, omega_in) > 0.0f) { @@ -63,15 +63,6 @@ ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure } } -ccl_device Spectrum bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h index a50df0b397d..04bc165af30 100644 --- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -44,10 +44,10 @@ ccl_device int bsdf_phong_ramp_setup(ccl_private PhongRampBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_phong_ramp_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc; float m_exponent = bsdf->exponent; @@ -70,15 +70,6 @@ ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure return zero_spectrum(); } -ccl_device float3 bsdf_phong_ramp_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); -} - ccl_device_inline float phong_ramp_exponent_to_roughness(float exponent) { return sqrt(1.0f / ((exponent + 2.0f) / 2.0f)); diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h index 39cca1bd970..be8ee78fcac 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h @@ -109,18 +109,17 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf * return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_diffuse_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc; - - float3 N = bsdf->N; - float3 V = I; // outgoing - float3 L = omega_in; // incoming + const float3 N = bsdf->N; if (dot(N, omega_in) > 0.0f) { + const float3 V = I; // outgoing + const float3 L = omega_in; // incoming *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; return bsdf_principled_diffuse_compute_brdf(bsdf, N, V, L, pdf); } @@ -130,15 +129,6 @@ ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const Shade } } -ccl_device Spectrum bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h index fa46f47eb21..f6499cc437c 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h +++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h @@ -59,19 +59,19 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd, return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc; - - float3 N = bsdf->N; - float3 V = I; // outgoing - float3 L = omega_in; // incoming - float3 H = normalize(L + V); + const float3 N = bsdf->N; if (dot(N, omega_in) > 0.0f) { + const float3 V = I; // outgoing + const float3 L = omega_in; // incoming + const float3 H = normalize(L + V); + *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; return calculate_principled_sheen_brdf(N, V, L, H, pdf); } @@ -81,15 +81,6 @@ ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderC } } -ccl_device Spectrum bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h index 798bcfaf9e7..2f761974e9a 100644 --- a/intern/cycles/kernel/closure/bsdf_reflection.h +++ b/intern/cycles/kernel/closure/bsdf_reflection.h @@ -18,19 +18,10 @@ ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf) return SD_BSDF; } -ccl_device Spectrum bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_reflection_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; return zero_spectrum(); diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h index 34836206ddf..e4f66245a0b 100644 --- a/intern/cycles/kernel/closure/bsdf_refraction.h +++ b/intern/cycles/kernel/closure/bsdf_refraction.h @@ -18,19 +18,10 @@ ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf) return SD_BSDF; } -ccl_device Spectrum bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_refraction_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; return zero_spectrum(); diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h index c9086823de9..9f78c86b3b7 100644 --- a/intern/cycles/kernel/closure/bsdf_toon.h +++ b/intern/cycles/kernel/closure/bsdf_toon.h @@ -49,33 +49,29 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth) return fminf(max_angle + smooth, M_PI_2_F); } -ccl_device Spectrum bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; - float max_angle = bsdf->size * M_PI_2_F; - float smooth = bsdf->smooth * M_PI_2_F; - float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f)); + float cosNI = dot(bsdf->N, omega_in); - float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); + if (cosNI >= 0.0f) { + float max_angle = bsdf->size * M_PI_2_F; + float smooth = bsdf->smooth * M_PI_2_F; + float angle = safe_acosf(fmaxf(cosNI, 0.0f)); - if (eval > 0.0f) { - float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); + float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); - *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle)); - return make_spectrum(*pdf * eval); + if (eval > 0.0f) { + float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); + + *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle)); + return make_spectrum(*pdf * eval); + } } - *pdf = 0.0f; - return zero_spectrum(); -} -ccl_device Spectrum bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ *pdf = 0.0f; return zero_spectrum(); } @@ -125,10 +121,10 @@ ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; float max_angle = bsdf->size * M_PI_2_F; @@ -153,15 +149,6 @@ ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosur return zero_spectrum(); } -ccl_device Spectrum bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h index c2aee1e1633..9306e82b579 100644 --- a/intern/cycles/kernel/closure/bsdf_transparent.h +++ b/intern/cycles/kernel/closure/bsdf_transparent.h @@ -59,19 +59,10 @@ ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd, } } -ccl_device Spectrum bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) -{ - *pdf = 0.0f; - return zero_spectrum(); -} - -ccl_device Spectrum bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_transparent_eval(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; return zero_spectrum(); diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h index a0ad7afe591..a39209bc937 100644 --- a/intern/cycles/kernel/integrator/mnee.h +++ b/intern/cycles/kernel/integrator/mnee.h @@ -807,7 +807,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len); /* Initialize throughput and evaluate receiver bsdf * |n.wo|. */ - surface_shader_bsdf_eval(kg, sd, wo, false, throughput, ls->shader); + surface_shader_bsdf_eval(kg, sd, wo, throughput, ls->shader); /* Update light sample with new position / direct.ion * and keep pdf in vertex area measure */ diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index 7c31d673566..c766ea2a07e 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -171,7 +171,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, Ray ray ccl_optional_struct_init; BsdfEval bsdf_eval ccl_optional_struct_init; - const bool is_transmission = surface_shader_is_transmission(sd, ls.D); + + const bool is_transmission = dot(ls.D, sd->N) < 0.0f; #ifdef __MNEE__ int mnee_vertex_count = 0; @@ -182,13 +183,15 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, const bool use_caustics = kernel_data_fetch(lights, ls.lamp).use_caustics; if (use_caustics) { /* Are we on a caustic caster? */ - if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) + if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) { return; + } /* Are we on a caustic receiver? */ - if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER)) + if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER)) { mnee_vertex_count = kernel_path_mnee_sample( kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval); + } } } } @@ -207,8 +210,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, } /* Evaluate BSDF. */ - const float bsdf_pdf = surface_shader_bsdf_eval( - kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader); + const float bsdf_pdf = surface_shader_bsdf_eval(kg, sd, ls.D, &bsdf_eval, ls.shader); bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf); if (ls.shader & SHADER_USE_MIS) { diff --git a/intern/cycles/kernel/integrator/surface_shader.h b/intern/cycles/kernel/integrator/surface_shader.h index 125aaae1b3f..7da81984a12 100644 --- a/intern/cycles/kernel/integrator/surface_shader.h +++ b/intern/cycles/kernel/integrator/surface_shader.h @@ -108,13 +108,6 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg, } /* BSDF */ - -ccl_device_inline bool surface_shader_is_transmission(ccl_private const ShaderData *sd, - const float3 omega_in) -{ - return dot(sd->N, omega_in) < 0.0f; -} - ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light_shader_flags) { if (!(light_shader_flags & SHADER_EXCLUDE_ANY)) { @@ -141,7 +134,6 @@ ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg, ccl_private ShaderData *sd, const float3 omega_in, - const bool is_transmission, ccl_private const ShaderClosure *skip_sc, ccl_private BsdfEval *result_eval, float sum_pdf, @@ -160,7 +152,7 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg, if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { if (CLOSURE_IS_BSDF(sc->type) && !_surface_shader_exclude(sc->type, light_shader_flags)) { float bsdf_pdf = 0.0f; - Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf); + Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf); if (bsdf_pdf != 0.0f) { bsdf_eval_accum(result_eval, sc->type, eval * sc->weight); @@ -184,14 +176,13 @@ ccl_device_inline surface_shader_bsdf_eval(KernelGlobals kg, ccl_private ShaderData *sd, const float3 omega_in, - const bool is_transmission, ccl_private BsdfEval *bsdf_eval, const uint light_shader_flags) { bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum()); return _surface_shader_bsdf_eval_mis( - kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags); + kg, sd, omega_in, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags); } /* Randomly sample a BSSRDF or BSDF proportional to ShaderClosure.sample_weight. */ @@ -285,10 +276,9 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg, bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight); if (sd->num_closure > 1) { - const bool is_transmission = surface_shader_is_transmission(sd, *omega_in); float sweight = sc->sample_weight; *pdf = _surface_shader_bsdf_eval_mis( - kg, sd, *omega_in, is_transmission, sc, bsdf_eval, *pdf * sweight, sweight, 0); + kg, sd, *omega_in, sc, bsdf_eval, *pdf * sweight, sweight, 0); } } |