Cycles: option to make background visible through glass transparent.
[blender-staging.git] / intern / cycles / kernel / closure / bsdf.h
index 558aa0dc6a9bef62ed18ce074a6238ecea16f4ab..6f0bdb3fa38214338c8d330b3dfed419bc26c379 100644 (file)
  * limitations under the License.
  */
 
-#include "../closure/bsdf_ashikhmin_velvet.h"
-#include "../closure/bsdf_diffuse.h"
-#include "../closure/bsdf_oren_nayar.h"
-#include "../closure/bsdf_phong_ramp.h"
-#include "../closure/bsdf_diffuse_ramp.h"
-#include "../closure/bsdf_microfacet.h"
-#include "../closure/bsdf_reflection.h"
-#include "../closure/bsdf_refraction.h"
-#include "../closure/bsdf_transparent.h"
-#include "../closure/bsdf_ashikhmin_shirley.h"
-#include "../closure/bsdf_toon.h"
-#include "../closure/bsdf_hair.h"
-#ifdef __SUBSURFACE__
-#include "../closure/bssrdf.h"
-#endif
+#include "kernel/closure/bsdf_ashikhmin_velvet.h"
+#include "kernel/closure/bsdf_diffuse.h"
+#include "kernel/closure/bsdf_oren_nayar.h"
+#include "kernel/closure/bsdf_phong_ramp.h"
+#include "kernel/closure/bsdf_diffuse_ramp.h"
+#include "kernel/closure/bsdf_microfacet.h"
+#include "kernel/closure/bsdf_microfacet_multi.h"
+#include "kernel/closure/bsdf_reflection.h"
+#include "kernel/closure/bsdf_refraction.h"
+#include "kernel/closure/bsdf_transparent.h"
+#include "kernel/closure/bsdf_ashikhmin_shirley.h"
+#include "kernel/closure/bsdf_toon.h"
+#include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_principled_diffuse.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
+#include "kernel/closure/bssrdf.h"
 #ifdef __VOLUME__
-#include "../closure/volume.h"
+#  include "kernel/closure/volume.h"
 #endif
 
 CCL_NAMESPACE_BEGIN
 
-ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+/* Returns the square of the roughness of the closure if it has roughness,
+ * 0 for singular closures and 1 otherwise. */
+ccl_device_inline float bsdf_get_roughness_squared(const ShaderClosure *sc)
 {
-       int label;
+       if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
+               return 0.0f;
+       }
 
-#ifdef __OSL__
-       if(kg->osl && sc->prim)
-               return OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
-#endif
+       if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
+               MicrofacetBsdf *bsdf = (MicrofacetBsdf*) sc;
+               return bsdf->alpha_x*bsdf->alpha_y;
+       }
+
+       return 1.0f;
+}
+
+ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
+                                       ShaderData *sd,
+                                       const ShaderClosure *sc,
+                                       float randu,
+                                       float randv,
+                                       float3 *eval,
+                                       float3 *omega_in,
+                                       differential3 *domega_in,
+                                       float *pdf)
+{
+       int label;
 
        switch(sc->type) {
                case CLOSURE_BSDF_DIFFUSE_ID:
                case CLOSURE_BSDF_BSSRDF_ID:
-                       label = bsdf_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
 #ifdef __SVM__
                case CLOSURE_BSDF_OREN_NAYAR_ID:
-                       label = bsdf_oren_nayar_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
-               /*case CLOSURE_BSDF_PHONG_RAMP_ID:
-                       label = bsdf_phong_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+#ifdef __OSL__
+               case CLOSURE_BSDF_PHONG_RAMP_ID:
+                       label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
-                       label = bsdf_diffuse_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
-                       break;*/
+                       break;
+#endif
                case CLOSURE_BSDF_TRANSLUCENT_ID:
-                       label = bsdf_translucent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_REFLECTION_ID:
-                       label = bsdf_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_REFRACTION_ID:
-                       label = bsdf_refraction_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_TRANSPARENT_ID:
-                       label = bsdf_transparent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, 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_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                       label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+                       label = bsdf_microfacet_multi_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in,  &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
+                       break;
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+                       label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in,  &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
+                       break;
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
-                       label = bsdf_microfacet_beckmann_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
                case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
-                       label = bsdf_ashikhmin_shirley_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
-                       label = bsdf_ashikhmin_velvet_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_DIFFUSE_TOON_ID:
-                       label = bsdf_diffuse_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_diffuse_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_GLOSSY_TOON_ID:
-                       label = bsdf_glossy_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_HAIR_REFLECTION_ID:
-                       label = bsdf_hair_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
-                       label = bsdf_hair_transmission_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+                       label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+#ifdef __PRINCIPLED__
+               case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+               case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+                       label = bsdf_principled_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+                       label = bsdf_principled_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
+#endif  /* __PRINCIPLED__ */
 #endif
 #ifdef __VOLUME__
                case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
-                       label = volume_henyey_greenstein_sample(sc, ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
 #endif
                default:
@@ -127,79 +173,116 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
                        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_roughness_squared(sc) <= threshold_squared) {
+                               label |= LABEL_TRANSMIT_TRANSPARENT;
+                       }
+               }
+       }
+
        return label;
 }
 
-ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
+#ifndef __KERNEL_CUDA__
+ccl_device
+#else
+ccl_device_forceinline
+#endif
+float3 bsdf_eval(KernelGlobals *kg,
+                 ShaderData *sd,
+                 const ShaderClosure *sc,
+                 const float3 omega_in,
+                 float *pdf)
 {
        float3 eval;
 
-#ifdef __OSL__
-       if(kg->osl && sc->prim)
-               return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf);
-#endif
-
-       if(dot(ccl_fetch(sd, Ng), omega_in) >= 0.0f) {
+       if(dot(sd->Ng, omega_in) >= 0.0f) {
                switch(sc->type) {
                        case CLOSURE_BSDF_DIFFUSE_ID:
                        case CLOSURE_BSDF_BSSRDF_ID:
-                               eval = bsdf_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
-                       /*case CLOSURE_BSDF_PHONG_RAMP_ID:
-                               eval = bsdf_phong_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+#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, ccl_fetch(sd, I), omega_in, pdf);
-                               break;*/
+                               eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+#endif
                        case CLOSURE_BSDF_TRANSLUCENT_ID:
-                               eval = bsdf_translucent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFLECTION_ID:
-                               eval = bsdf_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFRACTION_ID:
-                               eval = bsdf_refraction_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSPARENT_ID:
-                               eval = bsdf_transparent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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_ANISO_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                               eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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_ANISO_ID:
                        case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
-                               eval = bsdf_microfacet_beckmann_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
                        case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
-                               eval = bsdf_ashikhmin_shirley_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_HAIR_REFLECTION_ID:
-                               eval = bsdf_hair_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+#ifdef __PRINCIPLED__
+                       case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+                       case CLOSURE_BSDF_BSSRDF_PRINCIPLED_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;
+#endif  /* __PRINCIPLED__ */
 #endif
 #ifdef __VOLUME__
                        case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
-                               eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
                                break;
 #endif
                        default:
@@ -211,57 +294,77 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
                switch(sc->type) {
                        case CLOSURE_BSDF_DIFFUSE_ID:
                        case CLOSURE_BSDF_BSSRDF_ID:
-                               eval = bsdf_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSLUCENT_ID:
-                               eval = bsdf_translucent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFLECTION_ID:
-                               eval = bsdf_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFRACTION_ID:
-                               eval = bsdf_refraction_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSPARENT_ID:
-                               eval = bsdf_transparent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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_ANISO_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                               eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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_ANISO_ID:
                        case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
-                               eval = bsdf_microfacet_beckmann_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
                        case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
-                               eval = bsdf_ashikhmin_shirley_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_HAIR_REFLECTION_ID:
-                               eval = bsdf_hair_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               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, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+#ifdef __PRINCIPLED__
+                       case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+                       case CLOSURE_BSDF_BSSRDF_PRINCIPLED_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  /* __PRINCIPLED__ */
 #endif
 #ifdef __VOLUME__
                        case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
-                               eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf);
+                               eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
                                break;
 #endif
                        default:
@@ -275,19 +378,20 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
 
 ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
 {
-/* ToDo: do we want to blur volume closures? */
-
-#ifdef __OSL__
-       if(kg->osl && sc->prim) {
-               OSLShader::bsdf_blur(sc, roughness);
-               return;
-       }
-#endif
-
+       /* ToDo: do we want to blur volume closures? */
 #ifdef __SVM__
        switch(sc->type) {
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+                       bsdf_microfacet_multi_ggx_blur(sc, roughness);
+                       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_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                        bsdf_microfacet_ggx_blur(sc, roughness);
                        break;
@@ -306,5 +410,60 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
 #endif
 }
 
+ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
+{
+#ifdef __SVM__
+       switch(a->type) {
+               case CLOSURE_BSDF_TRANSPARENT_ID:
+                       return true;
+               case CLOSURE_BSDF_DIFFUSE_ID:
+               case CLOSURE_BSDF_BSSRDF_ID:
+               case CLOSURE_BSDF_TRANSLUCENT_ID:
+                       return bsdf_diffuse_merge(a, b);
+               case CLOSURE_BSDF_OREN_NAYAR_ID:
+                       return bsdf_oren_nayar_merge(a, b);
+               case CLOSURE_BSDF_REFLECTION_ID:
+               case CLOSURE_BSDF_REFRACTION_ID:
+               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_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+               case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+               case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+                       return bsdf_microfacet_merge(a, b);
+               case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+                       return bsdf_ashikhmin_velvet_merge(a, b);
+               case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+               case CLOSURE_BSDF_GLOSSY_TOON_ID:
+                       return bsdf_toon_merge(a, b);
+               case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+               case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+                       return bsdf_hair_merge(a, b);
+#ifdef __PRINCIPLED__
+               case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+               case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+                       return bsdf_principled_diffuse_merge(a, b);
+#endif
+#ifdef __VOLUME__
+               case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+                       return volume_henyey_greenstein_merge(a, b);
+#endif
+               default:
+                       return false;
+       }
+#else
+       return false;
+#endif
+}
+
 CCL_NAMESPACE_END