From 6d19da0b2d468f099e0c1f56392ab8a1750d114f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 22 Sep 2022 20:03:24 +0200 Subject: 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 --- intern/cycles/kernel/closure/bsdf.h | 266 ++++++--------- .../cycles/kernel/closure/bsdf_ashikhmin_shirley.h | 240 +++++++------ .../cycles/kernel/closure/bsdf_ashikhmin_velvet.h | 120 +++---- intern/cycles/kernel/closure/bsdf_diffuse.h | 34 +- intern/cycles/kernel/closure/bsdf_diffuse_ramp.h | 26 +- intern/cycles/kernel/closure/bsdf_hair.h | 44 +-- .../cycles/kernel/closure/bsdf_hair_principled.h | 194 +++++------ intern/cycles/kernel/closure/bsdf_microfacet.h | 379 +++++++++++---------- .../cycles/kernel/closure/bsdf_microfacet_multi.h | 74 +--- intern/cycles/kernel/closure/bsdf_oren_nayar.h | 17 +- intern/cycles/kernel/closure/bsdf_phong_ramp.h | 17 +- .../kernel/closure/bsdf_principled_diffuse.h | 24 +- .../cycles/kernel/closure/bsdf_principled_sheen.h | 27 +- intern/cycles/kernel/closure/bsdf_reflection.h | 17 +- intern/cycles/kernel/closure/bsdf_refraction.h | 17 +- intern/cycles/kernel/closure/bsdf_toon.h | 53 ++- intern/cycles/kernel/closure/bsdf_transparent.h | 17 +- intern/cycles/kernel/integrator/mnee.h | 2 +- intern/cycles/kernel/integrator/shade_surface.h | 12 +- intern/cycles/kernel/integrator/surface_shader.h | 16 +- 20 files changed, 680 insertions(+), 916 deletions(-) (limited to 'intern') 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); } } -- cgit v1.2.3