diff options
Diffstat (limited to 'intern/cycles/kernel/closure/bsdf.h')
-rw-r--r-- | intern/cycles/kernel/closure/bsdf.h | 805 |
1 files changed, 400 insertions, 405 deletions
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 246cc8290d5..fbda52d74c4 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -70,7 +70,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) { @@ -99,15 +103,22 @@ 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, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, - ccl_private differential3 *domega_in, - ccl_private float *pdf) + ccl_private float *pdf, + ccl_private float2 *sampled_roughness, + ccl_private float *eta) { /* For curves use the smooth normal, particularly for ribbons the geometric * normal gives too much darkening otherwise. */ @@ -116,119 +127,45 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, switch (sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - label = bsdf_diffuse_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; -#ifdef __SVM__ +#if defined(__SVM__) || defined(__OSL__) case CLOSURE_BSDF_OREN_NAYAR_ID: - label = bsdf_oren_nayar_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_oren_nayar_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; # ifdef __OSL__ case CLOSURE_BSDF_PHONG_RAMP_ID: - label = bsdf_phong_ramp_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_phong_ramp_sample( + sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness); + *eta = 1.0f; break; case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - label = bsdf_diffuse_ramp_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_diffuse_ramp_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; # endif case CLOSURE_BSDF_TRANSLUCENT_ID: - label = bsdf_translucent_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_translucent_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; case CLOSURE_BSDF_REFLECTION_ID: - label = bsdf_reflection_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_reflection_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, eta); + *sampled_roughness = zero_float2(); break; case CLOSURE_BSDF_REFRACTION_ID: - label = bsdf_refraction_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_refraction_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, eta); + *sampled_roughness = zero_float2(); break; case CLOSURE_BSDF_TRANSPARENT_ID: - label = bsdf_transparent_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_transparent_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = zero_float2(); + *eta = 1.0f; break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID: @@ -236,169 +173,65 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - label = bsdf_microfacet_ggx_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_microfacet_ggx_sample( + sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta); break; case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: - label = bsdf_microfacet_ggx_glass_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_microfacet_ggx_glass_sample( + sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - label = bsdf_microfacet_beckmann_sample(kg, - sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_microfacet_beckmann_sample( + kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta); break; case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: - label = bsdf_ashikhmin_shirley_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_ashikhmin_shirley_sample( + sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness); + *eta = 1.0f; break; case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - label = bsdf_ashikhmin_velvet_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; case CLOSURE_BSDF_DIFFUSE_TOON_ID: - label = bsdf_diffuse_toon_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_diffuse_toon_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; case CLOSURE_BSDF_GLOSSY_TOON_ID: - label = bsdf_glossy_toon_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_glossy_toon_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + // double check if this is valid + *sampled_roughness = one_float2(); + *eta = 1.0f; break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: - label = bsdf_hair_reflection_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_hair_reflection_sample( + sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness); + *eta = 1.0f; break; case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: - label = bsdf_hair_transmission_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_hair_transmission_sample( + sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness); + *eta = 1.0f; break; case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: label = bsdf_principled_hair_sample( - kg, sc, sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta); break; -# ifdef __PRINCIPLED__ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: - label = bsdf_principled_diffuse_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); + label = bsdf_principled_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; break; case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID: - label = bsdf_principled_sheen_sample(sc, - Ng, - sd->I, - sd->dI.dx, - sd->dI.dy, - randu, - randv, - eval, - omega_in, - &domega_in->dx, - &domega_in->dy, - pdf); - break; -# endif /* __PRINCIPLED__ */ + label = bsdf_principled_sheen_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf); + *sampled_roughness = one_float2(); + *eta = 1.0f; + break; #endif default: label = LABEL_NONE; @@ -420,11 +253,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); } } } @@ -437,189 +271,350 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, return label; } +ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg, + ccl_private const ShaderClosure *sc, + ccl_private float2 *roughness, + ccl_private float *eta) +{ + bool refractive = false; + float alpha = 1.0f; + switch (sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; +#ifdef __SVM__ + case CLOSURE_BSDF_OREN_NAYAR_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; +# ifdef __OSL__ + case CLOSURE_BSDF_PHONG_RAMP_ID: + alpha = phong_ramp_exponent_to_roughness(((ccl_private const PhongRampBsdf *)sc)->exponent); + *roughness = make_float2(alpha, alpha); + *eta = 1.0f; + break; + case CLOSURE_BSDF_DIFFUSE_RAMP_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; +# endif + case CLOSURE_BSDF_TRANSLUCENT_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; + case CLOSURE_BSDF_REFLECTION_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + *roughness = zero_float2(); + *eta = bsdf->ior; + break; + } + case CLOSURE_BSDF_REFRACTION_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + *roughness = zero_float2(); + // do we need to inverse eta?? + *eta = bsdf->ior; + break; + } + case CLOSURE_BSDF_TRANSPARENT_ID: + *roughness = zero_float2(); + *eta = 1.0f; + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID: + case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + *roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y); + refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; + *eta = refractive ? 1.0f / bsdf->ior : bsdf->ior; + break; + } + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + *roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y); + *eta = bsdf->ior; + break; + } + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + *roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y); + refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; + *eta = refractive ? 1.0f / bsdf->ior : bsdf->ior; + } break; + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + *roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y); + *eta = 1.0f; + break; + } + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; + case CLOSURE_BSDF_DIFFUSE_TOON_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; + case CLOSURE_BSDF_GLOSSY_TOON_ID: + // double check if this is valid + *roughness = one_float2(); + *eta = 1.0f; + break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + *roughness = make_float2(((ccl_private HairBsdf *)sc)->roughness1, + ((ccl_private HairBsdf *)sc)->roughness2); + *eta = 1.0f; + break; + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + *roughness = make_float2(((ccl_private HairBsdf *)sc)->roughness1, + ((ccl_private HairBsdf *)sc)->roughness2); + *eta = 1.0f; + break; + case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: + alpha = ((ccl_private PrincipledHairBSDF *)sc)->m0_roughness; + *roughness = make_float2(alpha, alpha); + *eta = ((ccl_private PrincipledHairBSDF *)sc)->eta; + break; + case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; + case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: + case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID: + *roughness = one_float2(); + *eta = 1.0f; + break; +#endif + default: + *roughness = one_float2(); + *eta = 1.0f; + break; + } +} + +ccl_device_inline int bsdf_label(const KernelGlobals kg, + ccl_private const ShaderClosure *sc, + const float3 omega_in) +{ + /* For curves use the smooth normal, particularly for ribbons the geometric + * normal gives too much darkening otherwise. */ + int label; + switch (sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + case CLOSURE_BSSRDF_BURLEY_ID: + case CLOSURE_BSSRDF_RANDOM_WALK_ID: + case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; +#ifdef __SVM__ + case CLOSURE_BSDF_OREN_NAYAR_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; +# ifdef __OSL__ + case CLOSURE_BSDF_PHONG_RAMP_ID: + label = LABEL_REFLECT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_DIFFUSE_RAMP_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; +# endif + case CLOSURE_BSDF_TRANSLUCENT_ID: + label = LABEL_TRANSMIT | LABEL_DIFFUSE; + break; + case CLOSURE_BSDF_REFLECTION_ID: + label = LABEL_REFLECT | LABEL_SINGULAR; + break; + case CLOSURE_BSDF_REFRACTION_ID: + label = LABEL_TRANSMIT | LABEL_SINGULAR; + break; + case CLOSURE_BSDF_TRANSPARENT_ID: + label = LABEL_TRANSMIT | LABEL_TRANSPARENT; + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID: + case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_REFLECT | LABEL_SINGULAR : + LABEL_REFLECT | LABEL_GLOSSY; + break; + } + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: { + ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; + label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_TRANSMIT | LABEL_SINGULAR : + LABEL_TRANSMIT | LABEL_GLOSSY; + break; + } + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: + label = (bsdf_is_transmission(sc, omega_in)) ? LABEL_TRANSMIT | LABEL_GLOSSY : + LABEL_REFLECT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: + label = LABEL_REFLECT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; + case CLOSURE_BSDF_DIFFUSE_TOON_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; + case CLOSURE_BSDF_GLOSSY_TOON_ID: + label = LABEL_REFLECT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_HAIR_REFLECTION_ID: + label = LABEL_REFLECT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: + label = LABEL_TRANSMIT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: + if (bsdf_is_transmission(sc, omega_in)) + label = LABEL_TRANSMIT | LABEL_GLOSSY; + else + label = LABEL_REFLECT | LABEL_GLOSSY; + break; + case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; + case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: + case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID: + label = LABEL_REFLECT | LABEL_DIFFUSE; + break; +#endif + default: + label = LABEL_NONE; + break; + } + + /* Test if BSDF sample should be treated as transparent for background. */ + if (label & LABEL_TRANSMIT) { + float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold; + + if (threshold_squared >= 0.0f) { + if (bsdf_get_specular_roughness_squared(sc) <= threshold_squared) { + label |= LABEL_TRANSMIT_TRANSPARENT; + } + } + } + return label; +} + #ifndef __KERNEL_CUDA__ ccl_device #else ccl_device_inline #endif - float3 + Spectrum bsdf_eval(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, const float3 omega_in, - const bool is_transmission, ccl_private float *pdf) { - float3 eval = zero_float3(); + 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; -#ifdef __SVM__ - case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_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(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_FRESNEL_V2_ID: - case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: - case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_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_GLASS_ID: - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: - eval = bsdf_microfacet_ggx_glass_eval_reflect(sc, sd->I, omega_in, pdf); - 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; -# ifdef __PRINCIPLED__ - 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: - case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID: - eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf); - break; -# endif /* __PRINCIPLED__ */ + 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_FRESNEL_V2_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: + case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_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_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: + eval = bsdf_microfacet_ggx_glass_eval(sc, sd->I, omega_in, pdf); + 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: + case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_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; -#ifdef __SVM__ - 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_FRESNEL_V2_ID: - case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID: - case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_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_GLASS_ID: - case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: - eval = bsdf_microfacet_ggx_glass_eval_transmit(sc, sd->I, omega_in, pdf); - 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; -# ifdef __PRINCIPLED__ - 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: - case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID: - eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf); - break; -# endif /* __PRINCIPLED__ */ -#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); @@ -630,7 +625,7 @@ ccl_device_inline ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float roughness) { /* TODO: do we want to blur volume closures? */ -#ifdef __SVM__ +#if defined(__SVM__) || defined(__OSL__) switch (sc->type) { case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID: |