Cycles:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 12 Sep 2011 13:13:56 +0000 (13:13 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 12 Sep 2011 13:13:56 +0000 (13:13 +0000)
* Fix missing update when editing objects with emission materials.
* Fix preview pass rendering set to 1 not showing full resolution.
* Fix CUDA runtime compiling failing due to missing cache directory.
* Use settings from first render layer for visibility and material override.

And a bunch of incomplete and still disabled code mostly related to closure
sampling.

43 files changed:
CMakeLists.txt
intern/cycles/CMakeLists.txt
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_mesh.cpp
intern/cycles/blender/blender_object.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/device/device.cpp
intern/cycles/device/device_cuda.cpp
intern/cycles/device/device_multi.cpp
intern/cycles/kernel/kernel_emission.h
intern/cycles/kernel/kernel_globals.h
intern/cycles/kernel/kernel_light.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/osl/osl_shader.h
intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h
intern/cycles/kernel/svm/bsdf_diffuse.h
intern/cycles/kernel/svm/bsdf_microfacet.h
intern/cycles/kernel/svm/bsdf_reflection.h
intern/cycles/kernel/svm/bsdf_refraction.h
intern/cycles/kernel/svm/bsdf_transparent.h
intern/cycles/kernel/svm/bsdf_ward.h
intern/cycles/kernel/svm/bsdf_westin.h
intern/cycles/kernel/svm/emissive.h
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_bsdf.h
intern/cycles/kernel/svm/svm_closure.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/kernel/svm/volume.h
intern/cycles/render/light.cpp
intern/cycles/render/mesh.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/object.cpp
intern/cycles/render/session.cpp
intern/cycles/render/session.h
intern/cycles/render/svm.cpp
intern/cycles/render/svm.h
intern/cycles/render/tile.cpp
intern/cycles/util/util_path.cpp
intern/cycles/util/util_path.h

index 279644550c24b44c2d965f57fa4d105fa054c20f..c24817fc672246b5ebdc35efb7f6d9a01583c957 100644 (file)
@@ -207,11 +207,10 @@ option(WITH_API_INSTALL     "Copy API header files into the blender install fold
 # Cycles
 option(WITH_CYCLES                     "Enable Cycles Render Engine" ON)
 OPTION(WITH_CYCLES_OSL         "Build with Open Shading Language support" OFF)
-OPTION(WITH_CYCLES_CUDA                "Build with CUDA support" OFF)
+OPTION(WITH_CYCLES_CUDA                "Build with CUDA binaries" OFF)
 OPTION(WITH_CYCLES_BLENDER     "Build Blender Python extension" ON)
 OPTION(WITH_CYCLES_PARTIO      "Build with Partio point cloud support (unfinished)" OFF)
 OPTION(WITH_CYCLES_NETWORK     "Build with network rendering support (unfinished)" OFF)
-OPTION(WITH_CYCLES_MULTI       "Build with network rendering support (unfinished)" OFF)
 OPTION(WITH_CYCLES_TEST                "Build cycles test application" OFF)
 
 # disable for now, but plan to support on all platforms eventually
index 05b9d4ad3bba335b7a31be189baad21988ef4cb9..74bac846aa41495903c68c60c6200c07c282c525 100644 (file)
@@ -41,10 +41,6 @@ if(WITH_CYCLES_NETWORK)
   add_definitions(-DWITH_NETWORK)
 endif()
 
-if(WITH_CYCLES_MULTI)
-  add_definitions(-DWITH_MULTI)
-endif()
-
 if(WITH_CYCLES_CUDA)
   add_definitions(-DWITH_CUDA_BINARIES)
 endif()
@@ -59,6 +55,7 @@ endif()
 
 add_definitions(-DWITH_OPENCL)
 add_definitions(-DWITH_CUDA)
+add_definitions(-DWITH_MULTI)
 
 include_directories(
        ${BOOST_INCLUDE_DIR}
index da99e4e23d633843679fab2d41df666ae3570eb3..992a698bbdddb75b2560359d1a167ad736c6091e 100644 (file)
@@ -140,6 +140,42 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
         sub.prop(cscene, "debug_bvh_type", text="")
         sub.prop(cscene, "debug_use_spatial_splits")
 
+class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
+    bl_label = "Layers"
+    bl_options = {'DEFAULT_CLOSED'}
+    COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+    def draw(self, context):
+        layout = self.layout
+
+        scene = context.scene
+        rd = scene.render
+
+        # row = layout.row()
+        # row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
+
+        # col = row.column(align=True)
+        # col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
+        # col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
+
+        row = layout.row()
+        # rl = rd.layers.active
+        rl = rd.layers[0]
+        row.prop(rl, "name")
+        #row.prop(rd, "use_single_layer", text="", icon_only=True)
+
+        split = layout.split()
+
+        col = split.column()
+        col.prop(scene, "layers", text="Scene")
+
+        col = split.column()
+        col.prop(rl, "layers", text="Layer")
+
+        layout.separator()
+
+        layout.prop(rl, "material_override", text="Material")
+
 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
     bl_label = "Post Processing"
     bl_options = {'DEFAULT_CLOSED'}
index 3fe4fa60a1670d585132db39b0b0c05d6171e060..f981be66eb41041407d6499f8b8143d881edc899 100644 (file)
@@ -223,8 +223,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
        vector<uint> used_shaders;
 
        BL::Object::material_slots_iterator slot;
-       for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
-               find_shader(slot->material(), used_shaders);
+       for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
+               if(render_layer.material_override)
+                       find_shader(render_layer.material_override, used_shaders);
+               else
+                       find_shader(slot->material(), used_shaders);
+       }
 
        if(used_shaders.size() == 0)
                used_shaders.push_back(scene->default_surface);
index f1ba2dba2f5e4d0d1465f63dbaa190cb31c201b2..e693efb2d7f0c4981862bca55616e6cbb21efe6a 100644 (file)
@@ -108,7 +108,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
 
 /* Object */
 
-void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
+void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint visibility)
 {
        /* light is handled separately */
        if(object_is_light(b_ob)) {
@@ -130,7 +130,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
                object->name = b_ob.name();
                object->tfm = tfm;
                
-               object->visibility = object_ray_visibility(b_ob);
+               object->visibility = object_ray_visibility(b_ob) & visibility;
                if(b_parent.ptr.data != b_ob.ptr.data)
                        object->visibility &= object_ray_visibility(b_parent);
 
@@ -147,12 +147,8 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
 void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
 {
        /* layer data */
-       uint layer;
-       
-       if(b_v3d)
-               layer = get_layer(b_v3d.layers());
-       else
-               layer = get_layer(b_scene.layers());
+       uint scene_layer = render_layer.scene_layer;
+       uint layer = render_layer.layer;
        
        /* prepare for sync */
        light_map.pre_sync();
@@ -165,8 +161,14 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
 
        for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
                bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
+               uint ob_layer = get_layer(b_ob->layers());
+
+               if(!hide && (ob_layer & scene_layer)) {
+                       uint visibility = PATH_RAY_ALL;
+                       
+                       if(!(ob_layer & layer))
+                               visibility &= ~PATH_RAY_CAMERA;
 
-               if(!hide && get_layer(b_ob->layers()) & layer) {
                        if(b_ob->is_duplicator()) {
                                /* dupli objects */
                                object_create_duplilist(*b_ob, b_scene);
@@ -176,7 +178,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
 
                                for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
                                        Transform tfm = get_transform(b_dup->matrix());
-                                       sync_object(*b_ob, b_index, b_dup->object(), tfm);
+                                       sync_object(*b_ob, b_index, b_dup->object(), tfm, visibility);
                                        b_index++;
                                }
 
@@ -185,7 +187,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
                        else {
                                /* object itself */
                                Transform tfm = get_transform(b_ob->matrix_world());
-                               sync_object(*b_ob, 0, *b_ob, tfm);
+                               sync_object(*b_ob, 0, *b_ob, tfm, visibility);
                        }
                }
        }
index ea5d0a1a3c60818537da05bcb83b68ac588668dc..b9d35a02a78004776642e775d8fede596c08289a 100644 (file)
@@ -118,6 +118,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d)
 {
        sync_integrator();
        sync_film();
+       sync_render_layer(b_v3d);
        sync_shaders();
        sync_objects(b_v3d);
 }
@@ -172,6 +173,29 @@ void BlenderSync::sync_film()
                filter->tag_update(scene);
 }
 
+/* Render Layer */
+
+void BlenderSync::sync_render_layer(BL::SpaceView3D b_v3d)
+{
+       if(b_v3d) {
+               render_layer.scene_layer = get_layer(b_v3d.layers());
+               render_layer.layer = render_layer.scene_layer;
+               render_layer.material_override = PointerRNA_NULL;
+       }
+       else {
+               BL::RenderSettings r = b_scene.render();
+               BL::RenderSettings::layers_iterator b_rlay;
+
+               for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
+                       render_layer.scene_layer = get_layer(b_scene.layers());
+                       render_layer.layer = get_layer(b_rlay->layers());
+                       render_layer.material_override = b_rlay->material_override();
+
+                       break; /* single layer for now */
+               }
+       }
+}
+
 /* Scene Parameters */
 
 SceneParams BlenderSync::get_scene_params(BL::Scene b_scene)
index fe60f42bc7581cb72763d97a5e1605dfa9d24471..48e755b3dcd841e7715e317d2755b85f98dd14c3 100644 (file)
@@ -72,11 +72,12 @@ private:
        void sync_integrator();
        void sync_view();
        void sync_world();
+       void sync_render_layer(BL::SpaceView3D b_v3d);
        void sync_shaders();
 
        void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
        Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
-       void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm);
+       void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint visibility);
        void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
 
        /* util */
@@ -99,6 +100,17 @@ private:
 
        Scene *scene;
        bool preview;
+
+       struct RenderLayerInfo {
+               RenderLayerInfo()
+               : scene_layer(0), layer(0),
+                 material_override(PointerRNA_NULL)
+               {}
+
+               uint scene_layer;
+               uint layer;
+               BL::Material material_override;
+       } render_layer;
 };
 
 CCL_NAMESPACE_END
index e21dce45d8093516154abbc6d67763e950aa0fac..ab57d7cfe86cf3fcf8772155fb3db2c2026758e4 100644 (file)
@@ -84,7 +84,7 @@ void Device::pixels_alloc(device_memory& mem)
 
 void Device::pixels_copy_from(device_memory& mem, int y, int w, int h)
 {
-       mem_copy_from(mem, sizeof(uchar)*4*y*w, sizeof(uchar)*4*w*h);
+       mem_copy_from(mem, sizeof(uint8_t)*4*y*w, sizeof(uint8_t)*4*w*h);
 }
 
 void Device::pixels_free(device_memory& mem)
@@ -104,7 +104,13 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, in
        glPixelZoom((float)width/(float)w, (float)height/(float)h);
        glRasterPos2f(0, y);
 
-       glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)rgba.data_pointer);
+       uint8_t *pixels = (uint8_t*)rgba.data_pointer;
+
+       /* for multi devices, this assumes the ineffecient method that we allocate
+          all pixels on the device even though we only render to a subset */
+       pixels += sizeof(uint8_t)*4*y*w;
+
+       glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 
        glRasterPos2f(0.0f, 0.0f);
        glPixelZoom(1.0f, 1.0f);
index 49ffd3d0834ed2099c0825ea1d6c16555abb26b1..7fc0afce1acf30fae0f7eca82e6b867a4ffb082b 100644 (file)
@@ -232,11 +232,16 @@ public:
                double starttime = time_dt();
                printf("Compiling CUDA kernel ...\n");
 
+               path_create_directories(cubin);
+
                string command = string_printf("%s -arch=sm_%d%d -m%d --cubin \"%s\" --use_fast_math "
                        "-o \"%s\" --ptxas-options=\"-v\" --maxrregcount=%d --opencc-options -OPT:Olimit=0 -I\"%s\" -DNVCC",
                        nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), maxreg, include.c_str());
 
-               system(command.c_str());
+               if(system(command.c_str()) == -1) {
+                       fprintf(stderr, "Failed to execute compilation command.\n");
+                       return "";
+               }
 
                /* verify if compilation succeeded */
                if(!path_exists(cubin)) {
@@ -708,9 +713,13 @@ public:
 
                        cuda_push_context();
 
+                       /* for multi devices, this assumes the ineffecient method that we allocate
+                          all pixels on the device even though we only render to a subset */
+                       size_t offset = sizeof(uint8_t)*4*y*w;
+
                        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pmem.cuPBO);
                        glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)offset);
                        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
                        
                        glEnable(GL_TEXTURE_2D);
@@ -729,11 +738,11 @@ public:
                        
                        glTexCoord2f(0.0f, 0.0f);
                        glVertex2f(0.0f, 0.0f);
-                       glTexCoord2f((float)w/(float)width, 0);
+                       glTexCoord2f((float)w/(float)pmem.w, 0.0f);
                        glVertex2f((float)width, 0.0f);
-                       glTexCoord2f((float)w/(float)width, (float)h/(float)height);
+                       glTexCoord2f((float)w/(float)pmem.w, (float)h/(float)pmem.h);
                        glVertex2f((float)width, (float)height);
-                       glTexCoord2f(0.0f, (float)h/(float)height);
+                       glTexCoord2f(0.0f, (float)h/(float)pmem.h);
                        glVertex2f(0.0f, (float)height);
 
                        glEnd();
index cae63596d3b9785c36e4ed20fddaa7f15f92f5f9..f2f6251685e77e6b925666cac46bdfbf6659056c 100644 (file)
@@ -47,9 +47,6 @@ public:
        MultiDevice(bool background_)
        : unique_ptr(1)
        {
-               /* enforce background for now */
-               background = true;
-
                Device *device;
 
                /* add CPU device */
@@ -125,6 +122,15 @@ public:
                return desc.str();
        }
 
+       bool load_kernels()
+       {
+               foreach(SubDevice& sub, devices)
+                       if(!sub.device->load_kernels())
+                               return false;
+
+               return true;
+       }
+
        void mem_alloc(device_memory& mem, MemoryType type)
        {
                foreach(SubDevice& sub, devices) {
@@ -219,12 +225,26 @@ public:
 
        void pixels_alloc(device_memory& mem)
        {
-               Device::pixels_alloc(mem);
+               foreach(SubDevice& sub, devices) {
+                       mem.device_pointer = 0;
+                       sub.device->pixels_alloc(mem);
+                       sub.ptr_map[unique_ptr] = mem.device_pointer;
+               }
+
+               mem.device_pointer = unique_ptr++;
        }
 
        void pixels_free(device_memory& mem)
        {
-               Device::pixels_free(mem);
+               device_ptr tmp = mem.device_pointer;
+
+               foreach(SubDevice& sub, devices) {
+                       mem.device_pointer = sub.ptr_map[tmp];
+                       sub.device->pixels_free(mem);
+                       sub.ptr_map.erase(sub.ptr_map.find(tmp));
+               }
+
+               mem.device_pointer = 0;
        }
 
        void pixels_copy_from(device_memory& mem, int y, int w, int h)
@@ -248,14 +268,16 @@ public:
        {
                device_ptr tmp = rgba.device_pointer;
                int i = 0, sub_h = h/devices.size();
+               int sub_height = height/devices.size();
 
                foreach(SubDevice& sub, devices) {
                        int sy = y + i*sub_h;
                        int sh = (i == (int)devices.size() - 1)? h - sub_h*i: sub_h;
+                       int sheight = (i == (int)devices.size() - 1)? height - sub_height*i: sub_height;
                        /* adjust math for w/width */
 
                        rgba.device_pointer = sub.ptr_map[tmp];
-                       sub.device->draw_pixels(rgba, sy, w, sh, width, height, transparent);
+                       sub.device->draw_pixels(rgba, sy, w, sh, width, sheight, transparent);
                        i++;
                }
 
index 6b6033e9ebd7b5a95a2c21953567e24eb3a54c79..58c9183e58a1472d8f75c80d45c72c37a2bafda3 100644 (file)
@@ -46,20 +46,29 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
        return eval;
 }
 
-__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, float rando,
-       float randu, float randv, Ray *ray, float3 *eval)
+__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
+       float randt, float rando, float randu, float randv, Ray *ray, float3 *eval)
 {
-       /* sample a position on a light */
        LightSample ls;
 
-       light_sample(kg, randt, randu, randv, sd->P, &ls);
+#ifdef __MULTI_LIGHT__
+       if(lindex != -1) {
+               /* sample position on a specified light */
+               light_select(kg, lindex, randu, randv, sd->P, &ls);
+       }
+       else
+#endif
+       {
+               /* sample a light and position on int */
+               light_sample(kg, randt, randu, randv, sd->P, &ls);
+       }
 
        /* compute incoming direction and distance */
        float t;
        float3 omega_in = normalize_len(ls.P - sd->P, &t);
 
        /* compute pdf */
-       float pdf = light_pdf(kg, &ls, -omega_in, t);
+       float pdf = light_sample_pdf(kg, &ls, -omega_in, t);
 
        /* evaluate closure */
        *eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -omega_in);
@@ -67,6 +76,8 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, fl
        if(is_zero(*eval) || pdf == 0.0f)
                return false;
 
+       /* todo: use visbility flag to skip lights */
+
        /* evaluate BSDF at shading point */
        float bsdf_pdf;
        float3 bsdf_eval = shader_bsdf_eval(kg, sd, omega_in, &bsdf_pdf);
@@ -88,10 +99,22 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, fl
                *eval *= 0.25f;
        }
 
-       /* setup ray */
-       ray->P = ray_offset(sd->P, sd->Ng);
-       ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
-       ray->D = normalize_len(ray->D, &ray->t);
+#if 0
+       /* todo: implement this in light */
+       bool no_shadow = true;
+
+       if(no_shadow) {
+               ray->t = 0.0f;
+       }
+       else {
+#endif
+               /* setup ray */
+               ray->P = ray_offset(sd->P, sd->Ng);
+               ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
+               ray->D = normalize_len(ray->D, &ray->t);
+#if 0
+       }
+#endif
 
        return true;
 }
index f37b27cc9f439aff529c70262bcab8a7ccb7cb87..a1b23128b387ce1b78dc3c1a31c12bf847072b99 100644 (file)
@@ -20,7 +20,7 @@
 
 #ifdef __KERNEL_CPU__
 
-#ifdef WITH_OSL
+#ifdef __OSL__
 #include "osl_globals.h"
 #endif
 
@@ -43,7 +43,7 @@ typedef struct KernelGlobals {
 
        KernelData __data;
 
-#ifdef WITH_OSL
+#ifdef __OSL__
        /* On the CPU, we also have the OSL globals here. Most data structures are shared
           with SVM, the difference is in the shaders and object/mesh attributes. */
        OSLGlobals osl;
index 5164e5deea25bedee72a1f01596e5f2794badfb6..77e73e932ef77952916dab25042fd3ecef38cd84 100644 (file)
@@ -129,7 +129,7 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
        }
 }
 
-__device float light_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
+__device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
 {
        float pdf;
 
@@ -141,5 +141,15 @@ __device float light_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
        return pdf;
 }
 
+__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls)
+{
+       point_light_sample(kg, index, randu, randv, P, ls);
+}
+
+__device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
+{
+       return point_light_pdf(kg, t);
+}
+
 CCL_NAMESPACE_END
 
index b073cd49a8c7613503925dd41bd963adf2ec1dd3..815eb4a1d539d3d48875c6d99d69ca9db792979c 100644 (file)
@@ -162,6 +162,86 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
        return average(throughput);
 }
 
+#ifdef __TRANSPARENT_SHADOWS__
+__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
+{
+       int prim = kernel_tex_fetch(__prim_index, isect->prim);
+       float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+       int shader = __float_as_int(Ns.w);
+
+       /* todo: add shader flag to check this */
+
+       return true;
+}
+#endif
+
+__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L)
+{
+       if(ray->t == 0.0f)
+               return false;
+       
+       bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW, isect);
+
+#ifdef __TRANSPARENT_SHADOWS__
+       if(result && kernel_data.integrator.transparent_shadows) {
+               /* transparent shadows work in such a way to try to minimize overhead
+                  in cases where we don't need them. after a regular shadow ray is
+                  cast we check if the hit primitive was potentially transparent, and
+                  only in that case start marching. this gives on extra ray cast for
+                  the cases were we do want transparency */
+               if(shader_transparent_shadow(kg, isect)) {
+                       /* todo: fix double contribution from indirect for triangle lights */
+                       /* if(kernel_data.integrator.transparent_shadows && (path_flag & PATH_RAY_TRANSPARENT)) */
+
+                       float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+                       float3 Pend = ray->P + ray->D*ray->t;
+                       int bounce = state->transparent_bounce;
+
+                       for(;;) {
+                               if(bounce >= kernel_data.integrator.transparent_max_bounce) {
+                                       return true;
+                               }
+                               else if(bounce >= kernel_data.integrator.transparent_min_bounce) {
+                                       /* todo: get random number somewhere for probabilistic terminate */
+#if 0
+                                       float probability = average(throughput);
+                                       float terminate = 0.0f; /* todo: get this random number */
+
+                                       if(terminate >= probability)
+                                               return true;
+
+                                       throughput /= probability;
+#endif
+                               }
+
+                               /* todo: fix it so we get first hit */
+                               if(!scene_intersect(kg, ray, PATH_RAY_SHADOW, isect)) {
+                                       *light_L *= throughput;
+                                       return false;
+                               }
+                               if(!shader_transparent_shadow(kg, isect))
+                                       return true;
+
+                               ShaderData sd;
+                               shader_setup_from_ray(kg, &sd, isect, ray);
+                               shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW); /* todo: state flag? */
+
+                               throughput *= shader_bsdf_transparency(kg, &sd);
+
+                               ray->P = ray_offset(sd.P, -sd.Ng);
+                               ray->t = len(Pend - ray->P);
+
+                               bounce++;
+                       }
+
+                       return true;
+               }
+       }
+#endif
+
+       return result;
+}
+
 __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
 {
        /* initialize */
@@ -247,13 +327,22 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
                                Ray light_ray;
                                float3 light_L;
 
-                               /* todo: use visbility flag to skip lights */
+#ifdef __MULTI_LIGHT__
+                               /* index -1 means randomly sample from distribution */
+                               int i = (kernel_data.integrator.num_distribution)? -1: 0;
 
-                               if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
-                                       /* trace shadow ray */
-                                       if(!scene_intersect(kg, &light_ray, PATH_RAY_SHADOW, &isect))
-                                               L += throughput*light_L;
+                               for(; i < kernel_data.integrator.num_all_lights; i++) {
+#else
+                               const int i = -1;
+#endif
+                                       if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
+                                               /* trace shadow ray */
+                                               if(!shadow_blocked(kg, &state, &light_ray, &isect, &light_L))
+                                                       L += throughput*light_L;
+                                       }
+#ifdef __MULTI_LIGHT__
                                }
+#endif
                        }
                }
 #endif
index 92d920b5c617ab111bd42d1b81aa75619668bb24..0cf2091590c38df29577f253e1a7a54336c0358e 100644 (file)
  *
  */
 
+
+#ifdef __OSL__
+
+#include "osl_shader.h"
+
+#else
+
 #include "svm/bsdf.h"
 #include "svm/emissive.h"
 #include "svm/volume.h"
 #include "svm/svm_bsdf.h"
 #include "svm/svm.h"
 
-#ifdef WITH_OSL
-#include "osl_shader.h"
 #endif
 
 CCL_NAMESPACE_BEGIN
@@ -270,96 +275,201 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
 
 /* BSDF */
 
-__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
-       float randu, float randv, float3 *eval,
-       float3 *omega_in, differential3 *domega_in, float *pdf)
+#ifdef __MULTI_CLOSURE__
+
+__device_inline float3 _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
+       int skip_bsdf, float3 sum_eval, float sum_pdf, float sum_sample_weight)
 {
-       int label;
+       for(int i = 0; i< sd->num_closure; i++) {
+               if(i == skip_bsdf)
+                       continue;
 
-       *pdf = 0.0f;
+               const ShaderClosure *sc = &sd->closure[i];
 
-#ifdef WITH_OSL
-       if(kg->osl.use)
-               label = OSLShader::bsdf_sample(sd, randu, randv, *eval, *omega_in, *domega_in, *pdf);
-       else
+               if(CLOSURE_IS_BSDF(sc->type)) {
+                       float bsdf_pdf = 0.0f;
+#ifdef __OSL__
+                       float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf);
+#else
+                       float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
 #endif
-               label = svm_bsdf_sample(sd, randu, randv, eval, omega_in, domega_in, pdf);
 
-       return label;
+                       if(bsdf_pdf != 0.0f) {
+                               sum_eval += eval*sc->weight;
+                               sum_pdf += bsdf_pdf*sc->sample_weight;
+                       }
+
+                       sum_sample_weight += sc->sample_weight;
+               }
+       }
+
+       *pdf = sum_pdf/sum_sample_weight;
+       return sum_eval;
 }
 
+#endif
+
 __device float3 shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
        const float3 omega_in, float *pdf)
 {
-       float3 eval;
-
+#ifdef __MULTI_CLOSURE__
+       return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, make_float3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f);
+#else
+       const ShaderClosure *sc = &sd->closure;
        *pdf = 0.0f;
+       return svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight;
+#endif
+}
 
-#ifdef WITH_OSL
-       if(kg->osl.use)
-               eval = OSLShader::bsdf_eval(sd, omega_in, *pdf);
-       else
+__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
+       float randu, float randv, float3 *eval,
+       float3 *omega_in, differential3 *domega_in, float *pdf)
+{
+#ifdef __MULTI_CLOSURE__
+       int sampled = 0;
+
+       if(sd->num_closure > 1) {
+               /* pick a BSDF closure based on sample weights */
+               float sum = 0.0f;
+
+               for(sampled = 0; sampled < sd->num_closure; sampled++) {
+                       const ShaderClosure *sc = &sd->closure[sampled];
+                       
+                       if(CLOSURE_IS_BSDF(sc->type))
+                               sum += sc->sample_weight;
+               }
+
+               float r = sd->randb_closure*sum;
+               sum = 0.0f;
+
+               for(sampled = 0; sampled < sd->num_closure; sampled++) {
+                       const ShaderClosure *sc = &sd->closure[sampled];
+                       
+                       if(CLOSURE_IS_BSDF(sc->type)) {
+                               sum += sd->closure[sampled].sample_weight;
+
+                               if(r <= sum)
+                                       break;
+                       }
+               }
+
+               if(sampled == sd->num_closure) {
+                       *pdf = 0.0f;
+                       return LABEL_NONE;
+               }
+       }
+
+       const ShaderClosure *sc = &sd->closure[sampled];
+       int label;
+
+       *pdf = 0.0f;
+#ifdef __OSL__
+       label = OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
+#else
+       label = svm_bsdf_sample(sd, sc, randu, randv, eval, omega_in, domega_in, pdf);
 #endif
-               eval = svm_bsdf_eval(sd, omega_in, pdf);
 
-       return eval;
+       *eval *= sc->weight;
+
+       if(sd->num_closure > 1 && *pdf != 0.0f) {
+               float sweight = sc->sample_weight;
+               *eval = _shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, *eval, *pdf*sweight, sweight);
+       }
+
+       return label;
+#else
+       /* sample the single closure that we picked */
+       *pdf = 0.0f;
+       int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, eval, omega_in, domega_in, pdf);
+       *eval *= sd->closure.weight;
+       return label;
+#endif
 }
 
 __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
 {
-#ifdef WITH_OSL
-       if(!kg->osl.use)
+#ifndef __OSL__
+#ifdef __MULTI_CLOSURE__
+       for(int i = 0; i< sd->num_closure; i++) {
+               ShaderClosure *sc = &sd->closure[i];
+
+               if(CLOSURE_IS_BSDF(sc->type))
+                       svm_bsdf_blur(sc, roughness);
+       }
+#else
+       svm_bsdf_blur(&sd->closure, roughness);
+#endif
 #endif
-               svm_bsdf_blur(sd, roughness);
 }
 
-/* Emission */
-
-__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
+__device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               return OSLShader::emissive_eval(sd);
+#ifdef __MULTI_CLOSURE__
+       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+       for(int i = 0; i< sd->num_closure; i++) {
+               ShaderClosure *sc = &sd->closure[i];
+
+               if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // XXX osl
+                       eval += sc->weight;
        }
+
+       return eval;
+#else
+       if(sd->closure.type == CLOSURE_BSDF_TRANSPARENT_ID)
+               return sd->closure.weight;
        else
+               return make_float3(0.0f, 0.0f, 0.0f);
 #endif
-       {
-               return svm_emissive_eval(sd);
-       }
 }
 
-__device void shader_emissive_sample(KernelGlobals *kg, ShaderData *sd,
-       float randu, float randv, float3 *eval, float3 *I, float *pdf)
+
+/* Emission */
+
+__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               OSLShader::emissive_sample(sd, randu, randv, eval, I, pdf);
-       }
-       else
+#ifdef __MULTI_CLOSURE__
+       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+       for(int i = 0; i < sd->num_closure; i++) {
+               ShaderClosure *sc = &sd->closure[i];
+
+               if(CLOSURE_IS_EMISSION(sc->type)) {
+#ifdef __OSL__
+                       eval += OSLShader::emissive_eval(sd)*sc->weight;
+#else
+                       eval += svm_emissive_eval(sd, sc)*sc->weight;
 #endif
-       {
-               svm_emissive_sample(sd, randu, randv, eval, I, pdf);
+               }
        }
+
+       return eval;
+#else
+       return svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
+#endif
 }
 
 /* Holdout */
 
 __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               return OSLShader::holdout_eval(sd);
+#ifdef __MULTI_CLOSURE__
+       float3 weight = make_float3(0.0f, 0.0f, 0.0f);
+
+       for(int i = 0; i < sd->num_closure; i++) {
+               ShaderClosure *sc = &sd->closure[i];
+
+               if(CLOSURE_IS_HOLDOUT(sc->type))
+                       weight += sc->weight;
        }
-       else
-#endif
-       {
-#ifdef __SVM__
-               if(sd->svm_closure == CLOSURE_HOLDOUT_ID)
-                       return make_float3(1.0f, 1.0f, 1.0f);
-               else
+
+       return weight;
+#else
+       if(sd->closure.type == CLOSURE_HOLDOUT_ID)
+               return make_float3(1.0f, 1.0f, 1.0f);
+
+       return make_float3(0.0f, 0.0f, 0.0f);
 #endif
-                       return make_float3(0.0f, 0.0f, 0.0f);
-       }
 }
 
 /* Surface Evaluation */
@@ -367,54 +477,54 @@ __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
 __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
        float randb, int path_flag)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               OSLShader::eval_surface(kg, sd, randb, path_flag);
-       }
-       else
-#endif
-       {
+#ifdef __OSL__
+       OSLShader::eval_surface(kg, sd, randb, path_flag);
+#else
+
 #ifdef __SVM__
-               svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
+       svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
 #else
-               bsdf_diffuse_setup(sd, sd->N);
-               sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
+       bsdf_diffuse_setup(sd, &sd->closure);
+       sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f);
 #endif
 
-#ifdef __CAUSTICS_TRICKS__
-               /* caustic tricks */
-               if((path_flag & PATH_RAY_DIFFUSE) && (sd->flag & SD_BSDF_GLOSSY)) {
-                       if(kernel_data.integrator.no_caustics) {
-                               sd->flag &= ~(SD_BSDF_GLOSSY|SD_BSDF_HAS_EVAL|SD_EMISSION);
-                               sd->svm_closure = NBUILTIN_CLOSURES;
-                               sd->svm_closure_weight = make_float3(0.0f, 0.0f, 0.0f);
-                       }
-                       else if(kernel_data.integrator.blur_caustics > 0.0f)
-                               shader_bsdf_blur(kg, sd, kernel_data.integrator.blur_caustics);
-               }
 #endif
-       }
 }
 
 /* Background Evaluation */
 
 __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               return OSLShader::eval_background(kg, sd, path_flag);
+#ifdef __OSL__
+       return OSLShader::eval_background(kg, sd, path_flag);
+#else
+
+#ifdef __SVM__
+       svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
+
+#ifdef __MULTI_CLOSURE__
+       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+       for(int i = 0; i< sd->num_closure; i++) {
+               const ShaderClosure *sc = &sd->closure[i];
+
+               if(CLOSURE_IS_BACKGROUND(sc->type))
+                       eval += sc->weight;
        }
+
+       return eval;
+#else
+       if(sd->closure.type == CLOSURE_BACKGROUND_ID)
+               return sd->closure.weight;
        else
+               return make_float3(0.8f, 0.8f, 0.8f);
 #endif
-       {
-#ifdef __SVM__
-               svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
+
 #else
-               sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
+       return make_float3(0.8f, 0.8f, 0.8f);
 #endif
 
-               return sd->svm_closure_weight;
-       }
+#endif
 }
 
 /* Volume */
@@ -422,15 +532,25 @@ __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int pa
 __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
        float3 omega_in, float3 omega_out)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               OSLShader::volume_eval_phase(sd, omega_in, omega_out);
-       }
-       else
+#ifdef __MULTI_CLOSURE__
+       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+       for(int i = 0; i< sd->num_closure; i++) {
+               const ShaderClosure *sc = &sd->closure[i];
+
+               if(CLOSURE_IS_VOLUME(sc->type)) {
+#ifdef __OSL__
+                       eval += OSLShader::volume_eval_phase(sd, omega_in, omega_out);
+#else
+                       eval += volume_eval_phase(sd, sc, omega_in, omega_out);
 #endif
-       {
-               return volume_eval_phase(sd, omega_in, omega_out);
+               }
        }
+
+       return eval;
+#else
+       return volume_eval_phase(sd, &sd->closure, omega_in, omega_out);
+#endif
 }
 
 /* Volume Evaluation */
@@ -438,17 +558,13 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
 __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
        float randb, int path_flag)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               OSLShader::eval_volume(kg, sd, randb, path_flag);
-       }
-       else
-#endif
-       {
 #ifdef __SVM__
-               svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
+#ifdef __OSL__
+       OSLShader::eval_volume(kg, sd, randb, path_flag);
+#else
+       svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
+#endif
 #endif
-       }
 }
 
 /* Displacement Evaluation */
@@ -456,27 +572,21 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
 __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
 {
        /* this will modify sd->P */
-
-#ifdef WITH_OSL
-       if(kg->osl.use) {
-               OSLShader::eval_displacement(kg, sd);
-       }
-       else
-#endif
-       {
 #ifdef __SVM__
-               svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
+#ifdef __OSL__
+       OSLShader::eval_displacement(kg, sd);
+#else
+       svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
+#endif
 #endif
-       }
 }
 
 /* Free ShaderData */
 
 __device void shader_release(KernelGlobals *kg, ShaderData *sd)
 {
-#ifdef WITH_OSL
-       if(kg->osl.use)
-               OSLShader::release(kg, sd);
+#ifdef __OSL__
+       OSLShader::release(kg, sd);
 #endif
 }
 
index 1417f2d5110806159008b3421d13a1e3a0c7e149..d3012324739a387a663f0c10c1c5a479f621be04 100644 (file)
@@ -34,6 +34,9 @@ CCL_NAMESPACE_BEGIN
 #define __BACKGROUND__
 #define __CAUSTICS_TRICKS__
 #define __VISIBILITY_FLAG__
+#define __RAY_DIFFERENTIALS__
+#define __CAMERA_CLIPPING__
+#define __INTERSECTION_REFINE__
 
 #ifndef __KERNEL_OPENCL__
 #define __SVM__
@@ -42,9 +45,13 @@ CCL_NAMESPACE_BEGIN
 #define __HOLDOUT__
 #endif
 
-#define __RAY_DIFFERENTIALS__
-#define __CAMERA_CLIPPING__
-#define __INTERSECTION_REFINE__
+#ifdef __KERNEL_CPU__
+//#define __MULTI_CLOSURE__
+//#define __MULTI_LIGHT__
+//#define __TRANSPARENT_SHADOWS__
+//#define __OSL__
+#endif
+
 //#define __SOBOL_FULL_SCREEN__
 //#define __MODIFY_TP__
 //#define __QBVH__
@@ -179,20 +186,27 @@ typedef enum AttributeElement {
        ATTR_ELEMENT_NONE
 } AttributeElement;
 
-/* OSL data */
+/* Closure data */
 
-#if !defined(__KERNEL_GPU__) && defined(WITH_OSL)
+#define MAX_CLOSURE 8
 
-#define MAX_OSL_CLOSURE 8
-
-struct FlatClosure {
-       void *prim;
+typedef struct ShaderClosure {
+       ClosureType type;
        float3 weight;
+
+#ifdef __MULTI_CLOSURE__
        float sample_weight;
-};
+#endif
 
+#ifdef __OSL__
+       void *prim;
+#else
+       float data0;
+       float data1;
 #endif
 
+} ShaderClosure;
+
 /* Shader Data
  *
  * Main shader state at a point on the surface or in a volume. All coordinates
@@ -244,34 +258,18 @@ typedef struct ShaderData {
        float3 dPdu, dPdv;
 #endif
 
-       /* SVM closure data. we always sample a single closure, to get fixed
-        * memory usage, svm_closure_data contains closure parameters. */
-       ClosureType svm_closure;
-       float3 svm_closure_weight;
-       float svm_closure_data0;
-       float svm_closure_data1;
-
-#if !defined(__KERNEL_GPU__) && defined(WITH_OSL)
-       /* OSL closure data and context. we store all closures flattened into
-        * lists per type, different from SVM. */
-       struct {
-               FlatClosure bsdf[MAX_OSL_CLOSURE];
-               FlatClosure emissive[MAX_OSL_CLOSURE];
-               FlatClosure volume[MAX_OSL_CLOSURE];
-               
-               int num_bsdf;
-               int num_emissive;
-               int num_volume;
-
-               float bsdf_sample_sum;
-               float emissive_sample_sum;
-               float volume_sample_sum;
-
-               float3 holdout_weight;
-
-               float randb;
-       } osl_closure;
+#ifdef __MULTI_CLOSURE__
+       /* Closure data, we store a fixed array of closures */
+       ShaderClosure closure[MAX_CLOSURE];
+       int num_closure;
+       float randb_closure;
+#else
+       /* Closure data, with a single sampled closure for low memory usage */
+       ShaderClosure closure;
+#endif
 
+#ifdef __OSL__
+       /* OSL context */
        void *osl_ctx;
 #endif
 } ShaderData;
@@ -352,11 +350,11 @@ typedef struct KernelSunSky {
 typedef struct KernelIntegrator {
        /* emission */
        int use_emission;
-       int num_triangles;
        int num_distribution;
-       int num_lights;
+       int num_all_lights;
        float pdf_triangles;
        float pdf_lights;
+       float pdf_pad;
 
        /* bounces */
        int min_bounce;
index 73ff4f414232d207f93efc6ac2e473a6cd424b1c..3f0b1610181e6a9b1ff159eeb7373a79903643d7 100644 (file)
@@ -119,13 +119,13 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
                OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
 
                if(prim) {
-                       FlatClosure flat;
-                       flat.prim = prim;
-                       flat.weight = weight;
+                       ShaderClosure sc;
+                       sc.prim = prim;
+                       sc.weight = weight;
 
                        switch(prim->category()) {
                                case ClosurePrimitive::BSDF: {
-                                       if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+                                       if(sd->num_closure == MAX_CLOSURE)
                                                return;
 
                                        OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim;
@@ -140,7 +140,8 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
                                        float sample_weight = fabsf(average(weight))*albedo;
                                        float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight;
 
-                                       flat.sample_weight = sample_weight;
+                                       sc.sample_weight = sample_weight;
+                                       sc.type = CLOSURE_BSDF_ID;
                                        sd->osl_closure.bsdf_sample_sum = sample_sum;
 
                                        /* scattering flags */
@@ -152,29 +153,35 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
                                                sd->flag |= SD_BSDF;
 
                                        /* add */
-                                       sd->osl_closure.bsdf[sd->osl_closure.num_bsdf++] = flat;
+                                       sd->closure[sd->num_closure++] = sc;
                                        break;
                                }
                                case ClosurePrimitive::Emissive: {
-                                       if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+                                       if(sd->num_closure == MAX_CLOSURE)
                                                return;
 
                                        /* sample weight */
                                        float sample_weight = fabsf(average(weight));
                                        float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight;
 
-                                       flat.sample_weight = sample_weight;
+                                       sc.sample_weight = sample_weight;
+                                       sc.type = CLOSURE_EMISSION_ID;
                                        sd->osl_closure.emissive_sample_sum = sample_sum;
 
                                        /* flag */
                                        sd->flag |= SD_EMISSION;
 
-                                       sd->osl_closure.emissive[sd->osl_closure.num_emissive++] = flat;
+                                       sd->closure[sd->num_closure++] = sc;
                                        break;
                                }
                                case ClosurePrimitive::Holdout:
-                                       sd->osl_closure.holdout_weight += weight;
+                                       if(sd->num_closure == MAX_CLOSURE)
+                                               return;
+
+                                       sc.sample_weight = 0.0f;
+                                       sc.type = CLOSURE_HOLDOUT_ID;
                                        sd->flag |= SD_HOLDOUT;
+                                       sd->closure[sd->num_closure++] = sc;
                                        break;
                                case ClosurePrimitive::BSSRDF:
                                case ClosurePrimitive::Debug:
@@ -213,12 +220,8 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
                ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
 
        /* flatten closure tree */
-       sd->osl_closure.bsdf_sample_sum = 0.0f;
-       sd->osl_closure.emissive_sample_sum = 0.0f;
-       sd->osl_closure.num_bsdf = 0;
-       sd->osl_closure.num_emissive = 0;
-       sd->osl_closure.holdout_weight = make_float3(0.0f, 0.0f, 0.0f);
-       sd->osl_closure.randb = randb;
+       sd->num_closure = 0;
+       sd->randb_closure = randb;
 
        if(globals->Ci) {
                bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
@@ -292,24 +295,25 @@ static void flatten_volume_closure_tree(ShaderData *sd,
                OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
 
                if(prim) {
-                       FlatClosure flat;
-                       flat.prim = prim;
-                       flat.weight = weight;
+                       ShaderClosure sc;
+                       sc.prim = prim;
+                       sc.weight = weight;
 
                        switch(prim->category()) {
                                case ClosurePrimitive::Volume: {
-                                       if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+                                       if(sd->num_closure == MAX_CLOSURE)
                                                return;
 
                                        /* sample weight */
                                        float sample_weight = fabsf(average(weight));
                                        float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight;
 
-                                       flat.sample_weight = sample_weight;
+                                       sc.sample_weight = sample_weight;
+                                       sc.type = CLOSURE_VOLUME_ID;
                                        sd->osl_closure.volume_sample_sum = sample_sum;
 
                                        /* add */
-                                       sd->osl_closure.volume[sd->osl_closure.num_volume++] = flat;
+                                       sd->closure[sd->num_closure++] = sc;
                                        break;
                                }
                                case ClosurePrimitive::Holdout:
@@ -389,183 +393,76 @@ void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
 
 /* BSDF Closure */
 
-int OSLShader::bsdf_sample(const ShaderData *sd, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
+int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
 {
-       OSL::BSDFClosure *sample_bsdf = NULL;
+       OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure*)sc->prim;
        int label = LABEL_NONE;
-       float r = sd->osl_closure.randb*sd->osl_closure.bsdf_sample_sum;
-       float sample_sum = 0.0f;
 
        pdf = 0.0f;
 
-       if(sd->osl_closure.bsdf_sample_sum == 0.0f)
-               return LABEL_NONE;
-
-       /* find a closure to sample */
-       for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
-               const FlatClosure *flat = &sd->osl_closure.bsdf[i];
-               sample_sum += flat->sample_weight;
-
-               if(r > sample_sum)
-                       continue;
-
-               /* sample BSDF closure */
-               sample_bsdf = (OSL::BSDFClosure*)flat->prim;
-               ustring ulabel;
-
-               ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
-                       TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
-                       randu, randv,
-                       TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
-                       pdf, TO_COLOR3(eval));
-
-               /* convert OSL label */
-               if(ulabel == OSL::Labels::REFLECT)
-                       label = LABEL_REFLECT;
-               else if(ulabel == OSL::Labels::TRANSMIT)
-                       label = LABEL_TRANSMIT;
-               else
-                       return LABEL_NONE; /* sampling failed */
-
-               /* convert scattering to our bitflag label */
-               ustring uscattering = sample_bsdf->scattering();
-
-               if(uscattering == OSL::Labels::DIFFUSE)
-                       label |= LABEL_DIFFUSE;
-               else if(uscattering == OSL::Labels::GLOSSY)
-                       label |= LABEL_GLOSSY;
-               else if(uscattering == OSL::Labels::SINGULAR)
-                       label |= LABEL_SINGULAR;
-               else
-                       label |= LABEL_TRANSPARENT;
-
-               /* eval + pdf */
-               eval *= flat->weight;
-               pdf *= flat->sample_weight;
-
-               break;
-       }
-
-       if(!sample_bsdf || pdf == 0.0f)
-               return LABEL_NONE;
-
-       /* add eval/pdf from other BSDF closures */
-       for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
-               const FlatClosure *flat = &sd->osl_closure.bsdf[i];
-               OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
-
-               if(bsdf != sample_bsdf) {
-                       OSL::Color3 bsdf_eval;
-                       float bsdf_pdf = 0.0f;
-
-                       if(dot(sd->Ng, omega_in) >= 0.0f)
-                               bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
-                       else
-                               bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
-
-                       if(bsdf_pdf != 0.0f) {
-                               eval += TO_FLOAT3(bsdf_eval)*flat->weight;
-                               pdf += bsdf_pdf*flat->sample_weight;
-                       }
-               }
-       }
-
-       pdf *= 1.0f/(sd->osl_closure.bsdf_sample_sum);
+       /* sample BSDF closure */
+       ustring ulabel;
+
+       ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
+               TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
+               randu, randv,
+               TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
+               pdf, TO_COLOR3(eval));
+
+       /* convert OSL label */
+       if(ulabel == OSL::Labels::REFLECT)
+               label = LABEL_REFLECT;
+       else if(ulabel == OSL::Labels::TRANSMIT)
+               label = LABEL_TRANSMIT;
+       else
+               return LABEL_NONE; /* sampling failed */
+
+       /* convert scattering to our bitflag label */
+       ustring uscattering = sample_bsdf->scattering();
+
+       if(uscattering == OSL::Labels::DIFFUSE)
+               label |= LABEL_DIFFUSE;
+       else if(uscattering == OSL::Labels::GLOSSY)
+               label |= LABEL_GLOSSY;
+       else if(uscattering == OSL::Labels::SINGULAR)
+               label |= LABEL_SINGULAR;
+       else
+               label |= LABEL_TRANSPARENT;
 
        return label;
 }
 
-float3 OSLShader::bsdf_eval(const ShaderData *sd, const float3& omega_in, float& pdf)
+float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
 {
-       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
-
-       pdf = 0.0f;
-
-       for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
-               const FlatClosure *flat = &sd->osl_closure.bsdf[i];
-               OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
-               OSL::Color3 bsdf_eval;
-               float bsdf_pdf = 0.0f;
-
-               if(dot(sd->Ng, omega_in) >= 0.0f)
-                       bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
-               else
-                       bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
-
-               if(bsdf_pdf != 0.0f) {
-                       eval += TO_FLOAT3(bsdf_eval)*flat->weight;
-                       pdf += bsdf_pdf*flat->sample_weight;
-               }
-       }
-
-       pdf *= 1.0f/sd->osl_closure.bsdf_sample_sum;
+       OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim;
+       OSL::Color3 bsdf_eval;
 
-       return eval;
+       if(dot(sd->Ng, omega_in) >= 0.0f)
+               bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
+       else
+               bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
+       
+       return TO_FLOAT3(bsdf_eval);
 }
 
 /* Emissive Closure */
 
-float3 OSLShader::emissive_eval(const ShaderData *sd)
+float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
 {
-       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
-
-       for(int i = 0; i < sd->osl_closure.num_emissive; i++) {
-               const FlatClosure *flat = &sd->osl_closure.emissive[i];
-               OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)flat->prim;
-               OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
-               eval += TO_FLOAT3(emissive_eval)*flat->weight;
-       }
+       OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)sc->prim;
+       OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
+       eval += TO_FLOAT3(emissive_eval);
 
        return eval;
 }
 
-void OSLShader::emissive_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *I, float *pdf)
-{
-       float r = sd->osl_closure.randb*sd->osl_closure.emissive_sample_sum;
-       float sample_sum = 0.0f;
-
-       *pdf = 0.0f;
-
-       if(sd->osl_closure.emissive_sample_sum == 0.0f)
-               return;
-
-       /* find a closure to sample */
-       for(int i = 0; i < sd->osl_closure.num_emissive; i++) {
-               const FlatClosure *flat = &sd->osl_closure.emissive[i];
-               sample_sum += flat->sample_weight;
-
-               if(r <= sample_sum) {
-                       /* sample emissive closure */
-                       OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)flat->prim;
-                       emissive->sample(TO_VEC3(sd->Ng), randu, randv, TO_VEC3(*I), *pdf);
-                       *eval = flat->weight;
-                       *pdf *= flat->sample_weight/sd->osl_closure.emissive_sample_sum;
-                       return;
-               }
-       }
-}
-
 /* Volume Closure */
 
-float3 OSLShader::volume_eval_phase(const ShaderData *sd, const float3 omega_in, const float3 omega_out)
-{
-       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
-
-       for(int i = 0; i < sd->osl_closure.num_volume; i++) {
-               const FlatClosure *flat = &sd->osl_closure.volume[i];
-               OSL::VolumeClosure *volume = (OSL::VolumeClosure*)flat->prim;
-               OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
-               eval += TO_FLOAT3(volume_eval)*flat->weight;
-       }
-
-       return eval;
-}
-
-/* Holdout Closure */
-
-float3 OSLShader::holdout_eval(const ShaderData *sd)
+float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
 {
-       return sd->osl_closure.holdout_weight;
+       OSL::VolumeClosure *volume = (OSL::VolumeClosure*)sc->prim;
+       OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
+       return TO_FLOAT3(volume_eval)*sc->weight;
 }
 
 CCL_NAMESPACE_END
index 9b578b159aee9815dddf4b14b83cd1ec65046533..6b1d402989b0209e22183c0da9060c1ead2b4a87 100644 (file)
@@ -46,6 +46,7 @@ namespace OSL = ::OSL;
 
 class OSLRenderServices;
 class Scene;
+class ShaderClosure;
 class ShaderData;
 class differential3;
 class KernelGlobals;
@@ -66,15 +67,16 @@ public:
        static void eval_displacement(KernelGlobals *kg, ShaderData *sd);
 
        /* sample & eval */
-       static int bsdf_sample(const ShaderData *sd, float randu, float randv,
+       static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
+               float randu, float randv,
                float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
-       static float3 bsdf_eval(const ShaderData *sd, const float3& omega_in, float& pdf);
-       static float3 emissive_eval(const ShaderData *sd);
-       static void emissive_sample(const ShaderData *sd, float randu, float randv,
-               float3 *eval, float3 *I, float *pdf);
-       static float3 volume_eval_phase(const ShaderData *sd, const float3 omega_in,
-               const float3 omega_out);
-       static float3 holdout_eval(const ShaderData *sd);
+       static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
+               const float3& omega_in, float& pdf);
+
+       static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
+
+       static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc,
+               const float3 omega_in, const float3 omega_out);
 
        /* release */
        static void release(KernelGlobals *kg, const ShaderData *sd);
index e94b33efaaeeae07e8d916a945616864a042963f..e16efebf5bbff4f4180336ffa47d264cb363566e 100644 (file)
@@ -40,24 +40,24 @@ typedef struct BsdfAshikhminVelvetClosure {
        float m_invsigma2;
 } BsdfAshikhminVelvetClosure;
 
-__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, float3 N, float sigma)
+__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, ShaderClosure *sc, float sigma)
 {
        sigma = fmaxf(sigma, 0.01f);
 
        float m_invsigma2 = 1.0f/(sigma * sigma);
 
-       sd->svm_closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+       sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
-       sd->svm_closure_data0 = m_invsigma2;
+       sc->data0 = m_invsigma2;
 }
 
-__device void bsdf_ashikhmin_velvet_blur(ShaderData *sd, float roughness)
+__device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_invsigma2 = sd->svm_closure_data0;
+       float m_invsigma2 = sc->data0;
        float3 m_N = sd->N;
 
        float cosNO = dot(m_N, I);
@@ -89,19 +89,19 @@ __device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const f
        return make_float3(0, 0, 0);
 }
 
-__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_invsigma2 = sd->svm_closure_data0;
+       float m_invsigma2 = sc->data0;
        float3 m_N = sd->N;
 
        // we are viewing the surface from above - send a ray out with uniform
index a917db86ff55ab1448c3a7e4618cd14f151496a0..e8a002cb84c58238aff0f48c7153d3650b52e642 100644 (file)
@@ -41,17 +41,17 @@ typedef struct BsdfDiffuseClosure {
        //float3 m_N;
 } BsdfDiffuseClosure;
 
-__device void bsdf_diffuse_setup(ShaderData *sd, float3 N)
+__device void bsdf_diffuse_setup(ShaderData *sd, ShaderClosure *sc)
 {
-       sd->svm_closure = CLOSURE_BSDF_DIFFUSE_ID;
+       sc->type = CLOSURE_BSDF_DIFFUSE_ID;
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
 }
 
-__device void bsdf_diffuse_blur(ShaderData *sd, float roughness)
+__device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        float3 m_N = sd->N;
 
@@ -60,17 +60,17 @@ __device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const float3 I,
        return make_float3(cos_pi, cos_pi, cos_pi);
 }
 
-__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_diffuse_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_diffuse_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_diffuse_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
        float3 m_N = sd->N;
 
@@ -99,22 +99,22 @@ typedef struct BsdfTranslucentClosure {
        //float3 m_N;
 } BsdfTranslucentClosure;
 
-__device void bsdf_translucent_setup(ShaderData *sd, float3 N)
+__device void bsdf_translucent_setup(ShaderData *sd, ShaderClosure *sc)
 {
-       sd->svm_closure = CLOSURE_BSDF_TRANSLUCENT_ID;
+       sc->type = CLOSURE_BSDF_TRANSLUCENT_ID;
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
 }
 
-__device void bsdf_translucent_blur(ShaderData *sd, float roughness)
+__device void bsdf_translucent_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        float3 m_N = sd->N;
 
@@ -123,12 +123,12 @@ __device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const float
        return make_float3 (cos_pi, cos_pi, cos_pi);
 }
 
-__device float bsdf_translucent_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_translucent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_translucent_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
        float3 m_N = sd->N;
 
index 0ca37eedc2259dd148b577a92853de20887c7944..3acd3ba4c85444bdfe13ea806825afa132f39367 100644 (file)
@@ -43,34 +43,34 @@ typedef struct BsdfMicrofacetGGXClosure {
        float m_eta;
 } BsdfMicrofacetGGXClosure;
 
-__device void bsdf_microfacet_ggx_setup(ShaderData *sd, float3 N, float ag, float eta, bool refractive)
+__device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive)
 {
        float m_ag = clamp(ag, 1e-5f, 1.0f);
        float m_eta = eta;
 
-       sd->svm_closure_data0 = m_ag;
-       sd->svm_closure_data1 = m_eta;
+       sc->data0 = m_ag;
+       sc->data1 = m_eta;
 
        if(refractive)
-               sd->svm_closure = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+               sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
        else
-               sd->svm_closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
+               sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
 
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
 }
 
-__device void bsdf_microfacet_ggx_blur(ShaderData *sd, float roughness)
+__device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
 {
-       float m_ag = sd->svm_closure_data0;
+       float m_ag = sc->data0;
        m_ag = fmaxf(roughness, m_ag);
-       sd->svm_closure_data0 = m_ag;
+       sc->data0 = m_ag;
 }
 
-__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_ag = sd->svm_closure_data0;
-       //float m_eta = sd->svm_closure_data1;
-       int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+       float m_ag = sc->data0;
+       //float m_eta = sc->data1;
+       int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
        float3 m_N = sd->N;
 
        if(m_refractive) return make_float3 (0, 0, 0);
@@ -103,11 +103,11 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const flo
        return make_float3 (0, 0, 0);
 }
 
-__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_ag = sd->svm_closure_data0;
-       float m_eta = sd->svm_closure_data1;
-       int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+       float m_ag = sc->data0;
+       float m_eta = sc->data1;
+       int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
        float3 m_N = sd->N;
 
        if(!m_refractive) return make_float3 (0, 0, 0);
@@ -139,16 +139,16 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const fl
        return make_float3 (out, out, out);
 }
 
-__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_ag = sd->svm_closure_data0;
-       float m_eta = sd->svm_closure_data1;
-       int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+       float m_ag = sc->data0;
+       float m_eta = sc->data1;
+       int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
        float3 m_N = sd->N;
 
        float cosNO = dot(m_N, sd->I);
@@ -268,34 +268,34 @@ typedef struct BsdfMicrofacetBeckmannClosure {
        float m_eta;
 } BsdfMicrofacetBeckmannClosure;
 
-__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, float3 N, float ab, float eta, bool refractive)
+__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive)
 {
        float m_ab = clamp(ab, 1e-5f, 1.0f);
        float m_eta = eta;
 
-       sd->svm_closure_data0 = m_ab;
-       sd->svm_closure_data1 = m_eta;
+       sc->data0 = m_ab;
+       sc->data1 = m_eta;
 
        if(refractive)
-               sd->svm_closure = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+               sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
        else
-               sd->svm_closure = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+               sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
 
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
 }
 
-__device void bsdf_microfacet_beckmann_blur(ShaderData *sd, float roughness)
+__device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
 {
-       float m_ab = sd->svm_closure_data0;
+       float m_ab = sc->data0;
        m_ab = fmaxf(roughness, m_ab);
-       sd->svm_closure_data0 = m_ab;
+       sc->data0 = m_ab;
 }
 
-__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_ab = sd->svm_closure_data0;
-       //float m_eta = sd->svm_closure_data1;
-       int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+       float m_ab = sc->data0;
+       //float m_eta = sc->data1;
+       int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
        float3 m_N = sd->N;
 
        if(m_refractive) return make_float3 (0, 0, 0);
@@ -330,11 +330,11 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, cons
        return make_float3 (0, 0, 0);
 }
 
-__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_ab = sd->svm_closure_data0;
-       float m_eta = sd->svm_closure_data1;
-       int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+       float m_ab = sc->data0;
+       float m_eta = sc->data1;
+       int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
        float3 m_N = sd->N;
 
        if(!m_refractive) return make_float3 (0, 0, 0);
@@ -368,16 +368,16 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con
        return make_float3 (out, out, out);
 }
 
-__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_ab = sd->svm_closure_data0;
-       float m_eta = sd->svm_closure_data1;
-       int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+       float m_ab = sc->data0;
+       float m_eta = sc->data1;
+       int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
        float3 m_N = sd->N;
 
        float cosNO = dot(m_N, sd->I);
index 4dad61704df6bbcbf16cd364b48052dc91ec62ab..f00b72c4869e70dc93a74846ddf378fae75c2d70 100644 (file)
@@ -41,34 +41,34 @@ typedef struct BsdfReflectionClosure {
        //float3 m_N;
 } BsdfReflectionClosure;
 
-__device void bsdf_reflection_setup(ShaderData *sd, float3 N)
+__device void bsdf_reflection_setup(ShaderData *sd, ShaderClosure *sc)
 {
-       sd->svm_closure = CLOSURE_BSDF_REFLECTION_ID;
+       sc->type = CLOSURE_BSDF_REFLECTION_ID;
        sd->flag |= SD_BSDF;
 }
 
-__device void bsdf_reflection_blur(ShaderData *sd, float roughness)
+__device void bsdf_reflection_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_reflection_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_reflection_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_reflection_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sd->svm_closure_data;
+       //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data;
        float3 m_N = sd->N;
 
        // only one direction is possible
index 93bd747eb3156f4a96f6d2938c449d513f8eafc6..07ef8633e0dfed0939b144ff8148973e7cdd297f 100644 (file)
@@ -41,36 +41,36 @@ typedef struct BsdfRefractionClosure {
        float m_eta;
 } BsdfRefractionClosure;
 
-__device void bsdf_refraction_setup(ShaderData *sd, float3 N, float eta)
+__device void bsdf_refraction_setup(ShaderData *sd, ShaderClosure *sc, float eta)
 {
-       sd->svm_closure_data0 = eta;
+       sc->data0 = eta;
 
-       sd->svm_closure = CLOSURE_BSDF_REFRACTION_ID;
+       sc->type = CLOSURE_BSDF_REFRACTION_ID;
        sd->flag |= SD_BSDF;
 }
 
-__device void bsdf_refraction_blur(ShaderData *sd, float roughness)
+__device void bsdf_refraction_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_refraction_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_refraction_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_refraction_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_eta = sd->svm_closure_data0;
+       float m_eta = sc->data0;
        float3 m_N = sd->N;
 
        float3 R, T;
index 1674f04955e7a98490d2de50fbba22a46f458d42..4425c4bf1041e77b0d1bf716e955fb1dea4ab805 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-__device void bsdf_transparent_setup(ShaderData *sd)
+__device void bsdf_transparent_setup(ShaderData *sd, ShaderClosure *sc)
 {
-       sd->svm_closure = CLOSURE_BSDF_TRANSPARENT_ID;
+       sc->type = CLOSURE_BSDF_TRANSPARENT_ID;
        sd->flag |= SD_BSDF;
 }
 
-__device void bsdf_transparent_blur(ShaderData *sd, float roughness)
+__device void bsdf_transparent_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_transparent_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_transparent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_transparent_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_transparent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
        // only one direction is possible
        *omega_in = -sd->I;
index 18967b3981ece7e9e8a49b3875ae9f4447222b12..d46baf099a6c13da3b30f10660d32e1363bc2b18 100644 (file)
@@ -44,28 +44,28 @@ typedef struct BsdfWardClosure {
        float m_ay;
 } BsdfWardClosure;
 
-__device void bsdf_ward_setup(ShaderData *sd, float3 N, float3 T, float ax, float ay)
+__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float3 T, float ax, float ay)
 {
        float m_ax = clamp(ax, 1e-5f, 1.0f);
        float m_ay = clamp(ay, 1e-5f, 1.0f);
 
-       sd->svm_closure_data0 = m_ax;
-       sd->svm_closure_data1 = m_ay;
+       sc->data0 = m_ax;
+       sc->data1 = m_ay;
 
-       sd->svm_closure = CLOSURE_BSDF_WARD_ID;
+       sc->type = CLOSURE_BSDF_WARD_ID;
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
 }
 
-__device void bsdf_ward_blur(ShaderData *sd, float roughness)
+__device void bsdf_ward_blur(ShaderClosure *sc, float roughness)
 {
-       sd->svm_closure_data0 = fmaxf(roughness, sd->svm_closure_data0);
-       sd->svm_closure_data1 = fmaxf(roughness, sd->svm_closure_data1);
+       sc->data0 = fmaxf(roughness, sc->data0);
+       sc->data1 = fmaxf(roughness, sc->data1);
 }
 
-__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_ax = sd->svm_closure_data0;
-       float m_ay = sd->svm_closure_data1;
+       float m_ax = sc->data0;
+       float m_ay = sc->data1;
        float3 m_N = sd->N;
        float3 m_T = normalize(sd->dPdu);
 
@@ -93,20 +93,20 @@ __device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const float3 I, con
        return make_float3 (0, 0, 0);
 }
 
-__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_ward_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_ward_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_ward_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_ax = sd->svm_closure_data0;
-       float m_ay = sd->svm_closure_data1;
+       float m_ax = sc->data0;
+       float m_ay = sc->data1;
        float3 m_N = sd->N;
        float3 m_T = normalize(sd->dPdu);
 
index 0f38deb08855a20006fe7a38b915746052245256..21e5018c4896b846939c6adb740b2f8ef8764b13 100644 (file)
@@ -42,26 +42,26 @@ typedef struct BsdfWestinBackscatterClosure {
        float m_invroughness;
 } BsdfWestinBackscatterClosure;
 
-__device void bsdf_westin_backscatter_setup(ShaderData *sd, float3 N, float roughness)
+__device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness)
 {
        roughness = clamp(roughness, 1e-5f, 1.0f);
        float m_invroughness = 1.0f/roughness;
 
-       sd->svm_closure = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
+       sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
-       sd->svm_closure_data0 = m_invroughness;
+       sc->data0 = m_invroughness;
 }
 
-__device void bsdf_westin_backscatter_blur(ShaderData *sd, float roughness)
+__device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
 {
-       float m_invroughness = sd->svm_closure_data0;
+       float m_invroughness = sc->data0;
        m_invroughness = min(1.0f/roughness, m_invroughness);
-       sd->svm_closure_data0 = m_invroughness;
+       sc->data0 = m_invroughness;
 }
 
-__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_invroughness = sd->svm_closure_data0;
+       float m_invroughness = sc->data0;
        float3 m_N = sd->N;
 
        // pdf is implicitly 0 (no indirect sampling)
@@ -76,19 +76,19 @@ __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const
        return make_float3 (0, 0, 0);
 }
 
-__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_westin_backscatter_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_invroughness = sd->svm_closure_data0;
+       float m_invroughness = sc->data0;
        float3 m_N = sd->N;
 
        float cosNO = dot(m_N, sd->I);
@@ -137,20 +137,20 @@ typedef struct BsdfWestinSheenClosure {
        float m_edginess;
 } BsdfWestinSheenClosure;
 
-__device void bsdf_westin_sheen_setup(ShaderData *sd, float3 N, float edginess)
+__device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess)
 {
-       sd->svm_closure = CLOSURE_BSDF_WESTIN_SHEEN_ID;
+       sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID;
        sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
-       sd->svm_closure_data0 = edginess;
+       sc->data0 = edginess;
 }
 
-__device void bsdf_westin_sheen_blur(ShaderData *sd, float roughness)
+__device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
 {
 }
 
-__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-       float m_edginess = sd->svm_closure_data0;
+       float m_edginess = sc->data0;
        float3 m_N = sd->N;
 
        // pdf is implicitly 0 (no indirect sampling)
@@ -165,19 +165,19 @@ __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const float
        return make_float3 (0, 0, 0);
 }
 
-__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
        return make_float3(0.0f, 0.0f, 0.0f);
 }
 
-__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
 {
        return 1.0f;
 }
 
-__device int bsdf_westin_sheen_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       float m_edginess = sd->svm_closure_data0;
+       float m_edginess = sc->data0;
        float3 m_N = sd->N;
 
        // we are viewing the surface from the right side - send a ray out with cosine
index ed2b2e4aee89eaeac5d31c9d776a77e6d2710eaf..8bd31751fb3cae18dccf577e4a8bbc2dcf3ac8f3 100644 (file)
@@ -42,23 +42,6 @@ __device float3 emissive_eval(const float3 Ng, const float3 I)
        return make_float3(res, res, res);
 }
 
-__device void emissive_sample(const float3 Ng, float randu, float randv, float3 *I, float *pdf)
-{
-       // We don't do anything sophisticated here for the step
-       // We just sample the whole cone uniformly to the cosine
-       float3 T, B;
-       make_orthonormals(Ng, &T, &B);
-       float phi = 2 * M_PI_F * randu;
-
-       float cosTheta = sqrtf(1.0f - 1.0f * randv);
-       float sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
-       *I = (cosf(phi) * sinTheta) * T +
-                                (sinf(phi) * sinTheta) * B +
-                                                        cosTheta  * Ng;
-
-       *pdf = M_1_PI_F;
-}
-
 /// Return the probability distribution function in the direction I,
 /// given the parameters and the light's surface normal.  This MUST match
 /// the PDF computed by sample().
@@ -68,15 +51,9 @@ __device float emissive_pdf(const float3 Ng, const float3 I)
        return (cosNO > 0.0f)? M_1_PI_F: 0.0f;
 }
 
-__device float3 svm_emissive_eval(ShaderData *sd)
-{
-       return sd->svm_closure_weight*emissive_eval(sd->Ng, sd->I);
-}
-
-__device void svm_emissive_sample(ShaderData *sd, float randu, float randv, float3 *eval, float3 *I, float *pdf)
+__device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc)
 {
-       *eval = sd->svm_closure_weight;
-       emissive_sample(sd->Ng, randu, randv, I, pdf);
+       return emissive_eval(sd->Ng, sd->I);
 }
 
 CCL_NAMESPACE_END
index 989c37c3cd02bd8af42b4defef7d2c167d80ec57..a5d95c1b39444999741d87e4acb090fead76617f 100644 (file)
@@ -47,14 +47,14 @@ CCL_NAMESPACE_BEGIN
 
 /* Stack */
 
-__device float3 stack_load_float3(float *stack, uint a)
+__device_inline float3 stack_load_float3(float *stack, uint a)
 {
        kernel_assert(a+2 < SVM_STACK_SIZE);
 
        return make_float3(stack[a+0], stack[a+1], stack[a+2]);
 }
 
-__device void stack_store_float3(float *stack, uint a, float3 f)
+__device_inline void stack_store_float3(float *stack, uint a, float3 f)
 {
        kernel_assert(a+2 < SVM_STACK_SIZE);
 
@@ -63,40 +63,40 @@ __device void stack_store_float3(float *stack, uint a, float3 f)
        stack[a+2] = f.z;
 }
 
-__device float stack_load_float(float *stack, uint a)
+__device_inline float stack_load_float(float *stack, uint a)
 {
        kernel_assert(a < SVM_STACK_SIZE);
 
        return stack[a];
 }
 
-__device float stack_load_float_default(float *stack, uint a, uint value)
+__device_inline float stack_load_float_default(float *stack, uint a, uint value)
 {
        return (a == (uint)SVM_STACK_INVALID)? __int_as_float(value): stack_load_float(stack, a);
 }
 
-__device void stack_store_float(float *stack, uint a, float f)
+__device_inline void stack_store_float(float *stack, uint a, float f)
 {
        kernel_assert(a < SVM_STACK_SIZE);
 
        stack[a] = f;
 }
 
-__device bool stack_valid(uint a)
+__device_inline bool stack_valid(uint a)
 {
        return a != (uint)SVM_STACK_INVALID;
 }
 
 /* Reading Nodes */
 
-__device uint4 read_node(KernelGlobals *kg, int *offset)
+__device_inline uint4 read_node(KernelGlobals *kg, int *offset)
 {
        uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
        (*offset)++;
        return node;
 }
 
-__device float4 read_node_float(KernelGlobals *kg, int *offset)
+__device_inline float4 read_node_float(KernelGlobals *kg, int *offset)
 {
        uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
        float4 f = make_float4(__int_as_float(node.x), __int_as_float(node.y), __int_as_float(node.z), __int_as_float(node.w));
@@ -104,7 +104,7 @@ __device float4 read_node_float(KernelGlobals *kg, int *offset)
        return f;
 }
 
-__device void decode_node_uchar4(uint i, uint *x, uint *y, uint *z, uint *w)
+__device_inline void decode_node_uchar4(uint i, uint *x, uint *y, uint *z, uint *w)
 {
        if(x) *x = (i & 0xFF);
        if(y) *y = ((i >> 8) & 0xFF);
@@ -154,8 +154,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
        float closure_weight = 1.0f;
        int offset = sd->shader;
 
-       sd->svm_closure = NBUILTIN_CLOSURES;
-       sd->svm_closure_weight = make_float3(0.0f, 0.0f, 0.0f);
+#ifdef __MULTI_CLOSURE__
+       sd->num_closure = 0;
+       sd->randb_closure = randb;
+#else
+       sd->closure.type = NBUILTIN_CLOSURES;
+#endif
 
        while(1) {
                uint4 node = read_node(kg, &offset);
@@ -169,16 +173,16 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
                                break;
                        }
                        case NODE_CLOSURE_BSDF:
-                               svm_node_closure_bsdf(sd, stack, node, randb);
+                               svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag);
                                break;
                        case NODE_CLOSURE_EMISSION:
-                               svm_node_closure_emission(sd);
+                               svm_node_closure_emission(sd, stack, node);
                                break;
                        case NODE_CLOSURE_BACKGROUND:
-                               svm_node_closure_background(sd);
+                               svm_node_closure_background(sd, node);
                                break;
                        case NODE_CLOSURE_HOLDOUT:
-                               svm_node_closure_holdout(sd);
+                               svm_node_closure_holdout(sd, stack, node);
                                break;
                        case NODE_CLOSURE_SET_WEIGHT:
                                svm_node_closure_set_weight(sd, node.y, node.z, node.w);
@@ -190,7 +194,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
                                svm_node_emission_weight(kg, sd, stack, node);
                                break;
                        case NODE_MIX_CLOSURE:
-                               svm_node_mix_closure(sd, stack, node.y, node.z, &offset, &randb);
+                               svm_node_mix_closure(sd, stack, node, &offset, &randb);
                                break;
                        case NODE_ADD_CLOSURE:
                                svm_node_add_closure(sd, stack, node.y, node.z, &offset, &randb, &closure_weight);
@@ -307,7 +311,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
                                break;
                        case NODE_END:
                        default:
-                               sd->svm_closure_weight *= closure_weight;
+#ifndef __MULTI_CLOSURE__
+                               sd->closure.weight *= closure_weight;
+#endif
                                return;
                }
        }
index 22985e9ace5435b2e485162568e71e0f43e60561..a1b39c6ca1e22fdcdb55c8af8d127812cc4cbcf0 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-__device int svm_bsdf_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+__device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
 {
        int label;
 
-       switch(sd->svm_closure) {
+       switch(sc->type) {
                case CLOSURE_BSDF_DIFFUSE_ID:
-                       label = bsdf_diffuse_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_diffuse_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
 #ifdef __SVM__
                case CLOSURE_BSDF_TRANSLUCENT_ID:
-                       label = bsdf_translucent_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_translucent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_REFLECTION_ID:
-                       label = bsdf_reflection_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_reflection_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_REFRACTION_ID:
-                       label = bsdf_refraction_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_refraction_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_TRANSPARENT_ID:
-                       label = bsdf_transparent_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_transparent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_MICROFACET_GGX_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                       label = bsdf_microfacet_ggx_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_microfacet_ggx_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
-                       label = bsdf_microfacet_beckmann_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_microfacet_beckmann_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
 #ifdef __DPDU__
                case CLOSURE_BSDF_WARD_ID:
-                       label = bsdf_ward_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_ward_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
 #endif
                case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
-                       label = bsdf_ashikhmin_velvet_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_ashikhmin_velvet_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
-                       label = bsdf_westin_backscatter_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_westin_backscatter_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_WESTIN_SHEEN_ID:
-                       label = bsdf_westin_sheen_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       label = bsdf_westin_sheen_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
 #endif
                default:
@@ -78,53 +78,51 @@ __device int svm_bsdf_sample(const ShaderData *sd, float randu, float randv, flo
                        break;
        }
 
-       *eval *= sd->svm_closure_weight;
-
        return label;
 }
 
-__device float3 svm_bsdf_eval(const ShaderData *sd, const float3 omega_in, float *pdf)
+__device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
 {
        float3 eval;
 
        if(dot(sd->Ng, omega_in) >= 0.0f) {
-               switch(sd->svm_closure) {
+               switch(sc->type) {
                        case CLOSURE_BSDF_DIFFUSE_ID:
-                               eval = bsdf_diffuse_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSLUCENT_ID:
-                               eval = bsdf_translucent_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFLECTION_ID:
-                               eval = bsdf_reflection_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_reflection_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFRACTION_ID:
-                               eval = bsdf_refraction_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_refraction_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSPARENT_ID:
-                               eval = bsdf_transparent_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_transparent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_MICROFACET_GGX_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                               eval = bsdf_microfacet_ggx_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_microfacet_ggx_eval_reflect(sd, 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(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_microfacet_beckmann_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
 #ifdef __DPDU__
                        case CLOSURE_BSDF_WARD_ID:
-                               eval = bsdf_ward_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_ward_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
 #endif
                        case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
-                               eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
-                               eval = bsdf_westin_backscatter_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_westin_backscatter_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_WESTIN_SHEEN_ID:
-                               eval = bsdf_westin_sheen_eval_reflect(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
                        default:
                                eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -132,43 +130,43 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const float3 omega_in, float
                }
        }
        else {
-               switch(sd->svm_closure) {
+               switch(sc->type) {
                        case CLOSURE_BSDF_DIFFUSE_ID:
-                               eval = bsdf_diffuse_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSLUCENT_ID:
-                               eval = bsdf_translucent_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFLECTION_ID:
-                               eval = bsdf_reflection_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_reflection_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_REFRACTION_ID:
-                               eval = bsdf_refraction_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_refraction_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_TRANSPARENT_ID:
-                               eval = bsdf_transparent_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_transparent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_MICROFACET_GGX_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                               eval = bsdf_microfacet_ggx_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_microfacet_ggx_eval_transmit(sd, 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(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_microfacet_beckmann_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
 #ifdef __DPDU__
                        case CLOSURE_BSDF_WARD_ID:
-                               eval = bsdf_ward_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_ward_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
 #endif
                        case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
-                               eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
-                               eval = bsdf_westin_backscatter_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_westin_backscatter_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_WESTIN_SHEEN_ID:
-                               eval = bsdf_westin_sheen_eval_transmit(sd, sd->I, omega_in, pdf);
+                               eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
                        default:
                                eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -176,50 +174,48 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const float3 omega_in, float
                }
        }
 
-       eval *= sd->svm_closure_weight;
-
        return eval;
 }
 
-__device void svm_bsdf_blur(ShaderData *sd, float roughness)
+__device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
 {
-       switch(sd->svm_closure) {
+       switch(sc->type) {
                case CLOSURE_BSDF_DIFFUSE_ID:
-                       bsdf_diffuse_blur(sd, roughness);
+                       bsdf_diffuse_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_TRANSLUCENT_ID:
-                       bsdf_translucent_blur(sd, roughness);
+                       bsdf_translucent_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_REFLECTION_ID:
-                       bsdf_reflection_blur(sd, roughness);
+                       bsdf_reflection_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_REFRACTION_ID:
-                       bsdf_refraction_blur(sd, roughness);
+                       bsdf_refraction_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_TRANSPARENT_ID:
-                       bsdf_transparent_blur(sd, roughness);
+                       bsdf_transparent_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_MICROFACET_GGX_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
-                       bsdf_microfacet_ggx_blur(sd, roughness);
+                       bsdf_microfacet_ggx_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
-                       bsdf_microfacet_beckmann_blur(sd, roughness);
+                       bsdf_microfacet_beckmann_blur(sc, roughness);
                        break;
 #ifdef __DPDU__
                case CLOSURE_BSDF_WARD_ID:
-                       bsdf_ward_blur(sd, roughness);
+                       bsdf_ward_blur(sc, roughness);
                        break;
 #endif
                case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
-                       bsdf_ashikhmin_velvet_blur(sd, roughness);
+                       bsdf_ashikhmin_velvet_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
-                       bsdf_westin_backscatter_blur(sd, roughness);
+                       bsdf_westin_backscatter_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_WESTIN_SHEEN_ID:
-                       bsdf_westin_sheen_blur(sd, roughness);
+                       bsdf_westin_sheen_blur(sc, roughness);
                        break;
                default:
                        break;
index 1efadcefbd51f73bf0dd466f3be3a26e161e493f..aaf2926f60d137c07d6566e32933a5b8566d7ec4 100644 (file)
@@ -20,28 +20,92 @@ CCL_NAMESPACE_BEGIN
 
 /* Closure Nodes */
 
-__device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, float randb)
+__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
+{
+       if(type == CLOSURE_BSDF_REFRACTION_ID) {
+               if(refract)
+                       bsdf_refraction_setup(sd, sc, eta);
+               else
+                       bsdf_reflection_setup(sd, sc);
+       }
+       else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
+               bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract);
+       }
+       else
+               bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract);
+}
+
+__device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd)
+{
+#ifdef __MULTI_CLOSURE__
+       ShaderClosure *sc = &sd->closure[sd->num_closure];
+
+       if(sd->num_closure < MAX_CLOSURE)
+               sd->num_closure++;
+
+       return sc;
+#else
+       return &sd->closure;
+#endif
+}
+
+__device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight)
+{
+#ifdef __MULTI_CLOSURE__
+       sc->weight *= mix_weight;
+       sc->sample_weight = fabsf(average(sc->weight));
+#endif
+}
+
+__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag)
 {
        uint type, param1_offset, param2_offset;
+
+#ifdef __MULTI_CLOSURE__
+       uint mix_weight_offset;
+       decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
+       float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
+
+       if(mix_weight == 0.0f)
+               return;
+#else
        decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL);
+       float mix_weight = 1.0f;
+#endif
 
        float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z);
        float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w);
 
        switch(type) {
-               case CLOSURE_BSDF_DIFFUSE_ID:
-                       bsdf_diffuse_setup(sd, sd->N);
+               case CLOSURE_BSDF_DIFFUSE_ID: {
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+                       bsdf_diffuse_setup(sd, sc);
                        break;
-               case CLOSURE_BSDF_TRANSLUCENT_ID:
-                       bsdf_translucent_setup(sd, sd->N);
+               }
+               case CLOSURE_BSDF_TRANSLUCENT_ID: {
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+                       bsdf_translucent_setup(sd, sc);
                        break;
-               case CLOSURE_BSDF_TRANSPARENT_ID:
-                       bsdf_transparent_setup(sd);
+               }
+               case CLOSURE_BSDF_TRANSPARENT_ID: {
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+                       bsdf_transparent_setup(sd, sc);
                        break;
+               }
                case CLOSURE_BSDF_REFLECTION_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
-                       /* roughness */
+#ifdef __CAUSTICS_TRICKS__
+                       if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+                               break;
+#endif
+
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+
                        /* index of refraction */
                        float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f);
                        eta = 1.0f/eta;
@@ -49,26 +113,22 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
                        /* fresnel */
                        float cosNO = dot(sd->N, sd->I);
                        float fresnel = fresnel_dielectric_cos(cosNO, eta);
+                       float roughness = param1;
 
-                       sd->svm_closure_weight *= fresnel;
+                       sc->weight *= fresnel;
 
                        /* setup bsdf */
-                       if(type == CLOSURE_BSDF_REFLECTION_ID) {
-                               bsdf_reflection_setup(sd, sd->N);
-                       }
-                       else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) {
-                               float roughness = param1;
-                               bsdf_microfacet_beckmann_setup(sd, sd->N, roughness, eta, false);
-                       }
-                       else {
-                               float roughness = param1;
-                               bsdf_microfacet_ggx_setup(sd, sd->N, roughness, eta, false);
-                       }
+                       svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
                        break;
                }
                case CLOSURE_BSDF_REFRACTION_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
+#ifdef __CAUSTICS_TRICKS__
+                       if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+                               break;
+#endif
+
                        /* index of refraction */
                        float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f);
                        eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
@@ -76,34 +136,58 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
                        /* fresnel */
                        float cosNO = dot(sd->N, sd->I);
                        float fresnel = fresnel_dielectric_cos(cosNO, eta);
-                       bool refract = (fresnel < randb);
+                       float roughness = param1;
+
+#ifdef __MULTI_CLOSURE__
+                       /* reflection */
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+
+                       float3 weight = sc->weight;
+                       float sample_weight = sc->sample_weight;
+
+                       svm_node_closure_set_mix_weight(sc, mix_weight*fresnel);
+                       svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
+
+                       /* refraction */
+                       sc = svm_node_closure_get(sd);
+
+                       sc->weight = weight;
+                       sc->sample_weight = sample_weight;
+
+                       svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel));
+                       svm_node_glossy_setup(sd, sc, type, eta, roughness, true);
+#else
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+
+                       bool refract = (randb > fresnel);
+
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+                       svm_node_glossy_setup(sd, sc, type, eta, roughness, refract);
+#endif
 
-                       /* setup bsdf */
-                       if(type == CLOSURE_BSDF_REFRACTION_ID) {
-                               if(refract)
-                                       bsdf_refraction_setup(sd, sd->N, eta);
-                               else
-                                       bsdf_reflection_setup(sd, sd->N);
-                       }
-                       else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
-                               float roughness = param1;
-                               bsdf_microfacet_beckmann_setup(sd, sd->N, roughness, eta, refract);
-                       }
-                       else {
-                               float roughness = param1;
-                               bsdf_microfacet_ggx_setup(sd, sd->N, roughness, eta, refract);
-                       }
                        break;
                }
 #ifdef __DPDU__
                case CLOSURE_BSDF_WARD_ID: {
+#ifdef __CAUSTICS_TRICKS__
+                       if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+                               break;
+#endif
+
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+
                        float roughness_u = param1;
                        float roughness_v = param2;
-                       bsdf_ward_setup(sd, sd->N, normalize(sd->dPdu), roughness_u, roughness_v);
+
+                       bsdf_ward_setup(sd, sc, normalize(sd->dPdu), roughness_u, roughness_v);
                        break;
                }
 #endif
                case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
+                       ShaderClosure *sc = svm_node_closure_get(sd);
+                       svm_node_closure_set_mix_weight(sc, mix_weight);
+
                        /* sigma */
                        float sigma = clamp(param1, 0.0f, 1.0f);
 
@@ -115,55 +199,107 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
                        float cosNO = dot(sd->N, sd->I);
                        float fresnel = fresnel_dielectric_cos(cosNO, eta);
 
-                       sd->svm_closure_weight *= fresnel;
+                       sc->weight *= fresnel;
 
-                       bsdf_ashikhmin_velvet_setup(sd, sd->N, sigma);
+                       bsdf_ashikhmin_velvet_setup(sd, sc, sigma);
                        break;
                }
                default:
-                       return;
+                       break;
        }
 }
 
-__device void svm_node_closure_emission(ShaderData *sd)
+__device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
 {
-       sd->svm_closure = CLOSURE_EMISSION_ID;
+#ifdef __MULTI_CLOSURE__
+       ShaderClosure *sc = svm_node_closure_get(sd);
+       uint mix_weight_offset = node.y;
+
+       if(stack_valid(mix_weight_offset)) {
+               float mix_weight = stack_load_float(stack, mix_weight_offset);
+
+               if(mix_weight == 0.0f)
+                       return;
+
+               sc->weight *= mix_weight;
+       }
+#else
+       ShaderClosure *sc = &sd->closure;
+#endif
+
+       sc->type = CLOSURE_EMISSION_ID;
        sd->flag |= SD_EMISSION;
 }
 
-__device void svm_node_closure_background(ShaderData *sd)
+__device void svm_node_closure_background(ShaderData *sd, uint4 node)
 {
-       sd->svm_closure = CLOSURE_BACKGROUND_ID;
+#ifdef __MULTI_CLOSURE__
+       ShaderClosure *sc = svm_node_closure_get(sd);
+#else
+       ShaderClosure *sc = &sd->closure;
+#endif
+
+       sc->type = CLOSURE_BACKGROUND_ID;
 }
 
-__device void svm_node_closure_holdout(ShaderData *sd)
+__device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
 {
-       sd->svm_closure = CLOSURE_HOLDOUT_ID;
+#ifdef __MULTI_CLOSURE__
+       ShaderClosure *sc = svm_node_closure_get(sd);
+       uint mix_weight_offset = node.y;
+
+       if(stack_valid(mix_weight_offset)) {
+               float mix_weight = stack_load_float(stack, mix_weight_offset);
+
+               if(mix_weight == 0.0f)
+                       return;
+
+               sc->weight = make_float3(mix_weight, mix_weight, mix_weight);
+       }
+       else
+               sc->weight = make_float3(1.0f, 1.0f, 1.0f);
+
+       sc->sample_weight = 0.0f;
+#else
+       ShaderClosure *sc = &sd->closure;
+#endif
+
+       sc->type = CLOSURE_HOLDOUT_ID;
        sd->flag |= SD_HOLDOUT;
 }
 
 /* Closure Nodes */
 
+__device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
+{
+#ifdef __MULTI_CLOSURE__
+       sd->closure[sd->num_closure].weight = weight;
+#else
+       sd->closure.weight = weight;
+#endif
+}
+
 __device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
 {
-       sd->svm_closure_weight.x = __int_as_float(r);
-       sd->svm_closure_weight.y = __int_as_float(g);
-       sd->svm_closure_weight.z = __int_as_float(b);
+       float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
+       svm_node_closure_store_weight(sd, weight);
 }
 
 __device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b)
 {
-       sd->svm_closure_weight.x = __int_as_float(r);
-       sd->svm_closure_weight.y = __int_as_float(g);
-       sd->svm_closure_weight.z = __int_as_float(b);
+       float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
 
        if(sd->object != ~0)
-               sd->svm_closure_weight /= object_surface_area(kg, sd->object);
+               weight /= object_surface_area(kg, sd->object);
+
+       svm_node_closure_store_weight(sd, weight);
 }
 
 __device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
 {
-       sd->svm_closure_weight = stack_load_float3(stack, weight_offset);
+       float3 weight = stack_load_float3(stack, weight_offset);
+
+       svm_node_closure_store_weight(sd, weight);
 }
 
 __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@@ -172,37 +308,59 @@ __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float
        uint strength_offset = node.z;
        uint total_power = node.w;
 
-       sd->svm_closure_weight = stack_load_float3(stack, color_offset)*stack_load_float(stack, strength_offset);
+       float3 weight = stack_load_float3(stack, color_offset)*stack_load_float(stack, strength_offset);
 
        if(total_power && sd->object != ~0)
-               sd->svm_closure_weight /= object_surface_area(kg, sd->object);
+               weight /= object_surface_area(kg, sd->object);
+
+       svm_node_closure_store_weight(sd, weight);
 }
 
 __device void svm_node_mix_closure(ShaderData *sd, float *stack,
-       uint weight_offset, uint node_jump, int *offset, float *randb)
+       uint4 node, int *offset, float *randb)
 {
+#ifdef __MULTI_CLOSURE__
+       /* fetch weight from blend input, previous mix closures,
+          and write to stack to be used by closure nodes later */
+       uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
+       decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
+
        float weight = stack_load_float(stack, weight_offset);
-       weight = clamp(weight, 0.0f, 1.0f);
+       float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
 
+       if(stack_valid(weight1_offset))
+               stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
+       if(stack_valid(weight2_offset))
+               stack_store_float(stack, weight2_offset, in_weight*weight);
+#else
        /* pick a closure and make the random number uniform over 0..1 again.
           closure 1 starts on the next node, for closure 2 the start is at an
           offset from the current node, so we jump */
+       uint weight_offset = node.y;
+       uint node_jump = node.z;
+       float weight = stack_load_float(stack, weight_offset);
+       weight = clamp(weight, 0.0f, 1.0f);
+
        if(*randb < weight) {
                *offset += node_jump;
                *randb = *randb/weight;
        }
        else
                *randb = (*randb - weight)/(1.0f - weight);
+#endif
 }
 
 __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
        uint node_jump, int *offset, float *randb, float *closure_weight)
 {
-       float weight = 0.5f;
-
+#ifdef __MULTI_CLOSURE__
+       /* nothing to do, handled in compiler */
+#else
        /* pick one of the two closures with probability 0.5. sampling quality
           is not going to be great, for that we'd need to evaluate the weights
           of the two closures being added */
+       float weight = 0.5f;
+
        if(*randb < weight) {
                *offset += node_jump;
                *randb = *randb/weight;
@@ -211,6 +369,7 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
                *randb = (*randb - weight)/(1.0f - weight);
        
        *closure_weight *= 2.0f;
+#endif
 }
 
 CCL_NAMESPACE_END
index 758ba25c07a153aad45cb5f1abc8c787981f23c9..98e4a5ee5837412b35a347a9ea6085638cf840c8 100644 (file)
@@ -258,6 +258,7 @@ typedef enum ShaderType {
 /* Closure */
 
 typedef enum ClosureType {
+       CLOSURE_BSDF_ID,
        CLOSURE_BSDF_DIFFUSE_ID,
        CLOSURE_BSDF_TRANSLUCENT_ID,
        CLOSURE_BSDF_REFLECTION_ID,
@@ -272,16 +273,25 @@ typedef enum ClosureType {
        CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
        CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
        CLOSURE_BSDF_WESTIN_SHEEN_ID,
+
        CLOSURE_BSSRDF_CUBIC_ID,
        CLOSURE_EMISSION_ID,
        CLOSURE_DEBUG_ID,
        CLOSURE_BACKGROUND_ID,
        CLOSURE_HOLDOUT_ID,
        CLOSURE_SUBSURFACE_ID,
+       CLOSURE_VOLUME_ID,
 
        NBUILTIN_CLOSURES
 } ClosureType;
 
+/* watch this, being lazy with memory usage */
+#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_WESTIN_SHEEN_ID)
+#define CLOSURE_IS_VOLUME(type) (type == CLOSURE_VOLUME_ID)
+#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
+#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
+#define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
+
 CCL_NAMESPACE_END
 
 #endif /*  __SVM_TYPES_H__ */
index 32e0601ee00f73caf5555af43b38d9b41062dabd..dc377b5c59507ca617846a2f01825cb816e0c0bb 100644 (file)
@@ -34,7 +34,7 @@ CCL_NAMESPACE_BEGIN
 
 /* VOLUME CLOSURE */
 
-__device float3 volume_eval_phase(ShaderData *sd, const float3 omega_in, const float3 omega_out)
+__device float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
 {
        return make_float3(1.0f, 1.0f, 1.0f);
 }
index feb9e35e785ab986a7f3edc6658e692f12c000b2..b13cab554045db9351f10d21da7643647e0f9ac1 100644 (file)
@@ -55,6 +55,9 @@ LightManager::~LightManager()
 
 void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
 {
+       /* option to always sample all point lights */
+       bool multi_light = false;
+
        /* count */
        size_t num_lights = scene->lights.size();
        size_t num_triangles = 0;
@@ -82,7 +85,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
                }
        }
 
-       size_t num_distribution = num_triangles + num_lights;
+       size_t num_distribution = num_triangles;
+
+       if(!multi_light)
+               num_distribution += num_lights;
 
        /* emission area */
        float4 *distribution = dscene->light_distribution.resize(num_distribution + 1);
@@ -137,14 +143,16 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
        float trianglearea = totarea;
 
        /* point lights */
-       float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
-
-       for(size_t i = 0; i < scene->lights.size(); i++, offset++) {
-               distribution[offset].x = totarea;
-               distribution[offset].y = __int_as_float(-i-1);
-               distribution[offset].z = 1.0f;
-               distribution[offset].w = scene->lights[i]->radius;
-               totarea += lightarea;
+       if(!multi_light) {
+               float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
+
+               for(size_t i = 0; i < scene->lights.size(); i++, offset++) {
+                       distribution[offset].x = totarea;
+                       distribution[offset].y = __int_as_float(-i-1);
+                       distribution[offset].z = 1.0f;
+                       distribution[offset].w = scene->lights[i]->radius;
+                       totarea += lightarea;
+               }
        }
 
        /* normalize cumulative distribution functions */
@@ -163,28 +171,40 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 
        /* update device */
        KernelIntegrator *kintegrator = &dscene->data.integrator;
-       kintegrator->use_emission = (totarea > 0.0f);
+       kintegrator->use_emission = (totarea > 0.0f) || (multi_light && num_lights);
 
        if(kintegrator->use_emission) {
                /* number of emissives */
-               kintegrator->num_triangles = num_triangles;
-               kintegrator->num_lights = num_lights;
-               kintegrator->num_distribution = num_distribution;
+               kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
 
                /* precompute pdfs */
                kintegrator->pdf_triangles = 0.0f;
                kintegrator->pdf_lights = 0.0f;
 
-               if(trianglearea > 0.0f) {
-                       kintegrator->pdf_triangles = 1.0f/trianglearea;
+               if(multi_light) {
+                       /* sample one of all triangles and all lights */
+                       kintegrator->num_all_lights = num_lights;
+
+                       if(trianglearea > 0.0f)
+                               kintegrator->pdf_triangles = 1.0f/trianglearea;
                        if(num_lights)
-                               kintegrator->pdf_triangles *= 0.5f;
+                               kintegrator->pdf_lights = 1.0f;
                }
+               else {
+                       /* sample one, with 0.5 probability of light or triangle */
+                       kintegrator->num_all_lights = 0;
+
+                       if(trianglearea > 0.0f) {
+                               kintegrator->pdf_triangles = 1.0f/trianglearea;
+                               if(num_lights)
+                                       kintegrator->pdf_triangles *= 0.5f;
+                       }
 
-               if(num_lights) {
-                       kintegrator->pdf_lights = 1.0f/num_lights;
-                       if(trianglearea > 0.0f)
-                               kintegrator->pdf_lights *= 0.5f;
+                       if(num_lights) {
+                               kintegrator->pdf_lights = 1.0f/num_lights;
+                               if(trianglearea > 0.0f)
+                                       kintegrator->pdf_lights *= 0.5f;
+                       }
                }
 
                /* CDF */
index b73013fc378ca94e8e4f85a858c5846eb635a36a..7a6ce547486f6515d4525baa649509d633d246fb 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "device.h"
 #include "shader.h"
+#include "light.h"
 #include "mesh.h"
 #include "object.h"
 #include "scene.h"
@@ -250,6 +251,10 @@ void Mesh::tag_update(Scene *scene, bool rebuild)
 
        scene->mesh_manager->need_update = true;
        scene->object_manager->need_update = true;
+
+       foreach(uint sindex, used_shaders)
+               if(scene->shaders[sindex]->has_surface_emission)
+                       scene->light_manager->need_update = true;
 }
 
 /* Mesh Manager */
index 0ff774bce59725845d59c5805c2b6433889c4145..f20302568141d7064313bdbf60f4691473d5c869 100644 (file)
@@ -1024,7 +1024,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
        compiler.add_node(NODE_CLOSURE_BSDF,
                compiler.encode_uchar4(closure,
                        (param1)? param1->stack_offset: SVM_STACK_INVALID,
-                       (param2)? param2->stack_offset: SVM_STACK_INVALID),
+                       (param2)? param2->stack_offset: SVM_STACK_INVALID,
+                       compiler.closure_mix_weight_offset()),
                __float_as_int((param1)? param1->value.x: 0.0f),
                __float_as_int((param2)? param2->value.x: 0.0f));
 }
@@ -1222,8 +1223,6 @@ EmissionNode::EmissionNode()
 
 void EmissionNode::compile(SVMCompiler& compiler)
 {
-       compiler.add_node(NODE_CLOSURE_EMISSION, CLOSURE_EMISSION_ID);
-
        ShaderInput *color_in = input("Color");
        ShaderInput *strength_in = input("Strength");
 
@@ -1236,6 +1235,8 @@ void EmissionNode::compile(SVMCompiler& compiler)
                compiler.add_node(NODE_EMISSION_SET_WEIGHT_TOTAL, color_in->value * strength_in->value.x);
        else
                compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value * strength_in->value.x);
+
+       compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
 }
 
 void EmissionNode::compile(OSLCompiler& compiler)
@@ -1256,8 +1257,6 @@ BackgroundNode::BackgroundNode()
 
 void BackgroundNode::compile(SVMCompiler& compiler)
 {
-       compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID);
-
        ShaderInput *color_in = input("Color");
        ShaderInput *strength_in = input("Strength");
 
@@ -1268,6 +1267,8 @@ void BackgroundNode::compile(SVMCompiler& compiler)
        }
        else
                compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value*strength_in->value.x);
+
+       compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID);
 }
 
 void BackgroundNode::compile(OSLCompiler& compiler)
@@ -1285,7 +1286,7 @@ HoldoutNode::HoldoutNode()
 
 void HoldoutNode::compile(SVMCompiler& compiler)
 {
-       compiler.add_node(NODE_CLOSURE_HOLDOUT, CLOSURE_HOLDOUT_ID);
+       compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
 }
 
 void HoldoutNode::compile(OSLCompiler& compiler)
index fab051bde725dd267da253684abf2ece7ed03c04..1059254d5c48147be52c15ac1825c16eec225b10 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "device.h"
+#include "light.h"
 #include "mesh.h"
 #include "object.h"
 #include "scene.h"
@@ -83,8 +84,15 @@ void Object::apply_transform()
 
 void Object::tag_update(Scene *scene)
 {
-       if(mesh && mesh->transform_applied)
-               mesh->need_update = true;
+       if(mesh) {
+               if(mesh->transform_applied)
+                       mesh->need_update = true;
+
+               foreach(uint sindex, mesh->used_shaders)
+                       if(scene->shaders[sindex]->has_surface_emission)
+                               scene->light_manager->need_update = true;
+       }
+
        scene->mesh_manager->need_update = true;
        scene->object_manager->need_update = true;
 }
index 5fb687971ef1da79b24d6f04213d4a2e42cf4893..5eb8d51a8163f9366dd4df8db706c21739ad880e 100644 (file)
@@ -35,7 +35,7 @@ Session::Session(const SessionParams& params_)
 : params(params_),
   tile_manager(params.progressive, params.passes, params.tile_size, params.min_size)
 {
-       device_use_gl = ((params.device_type == DEVICE_CUDA || params.device_type == DEVICE_OPENCL) && !params.background);
+       device_use_gl = ((params.device_type != DEVICE_CPU) && !params.background);
 
        device = Device::create(params.device_type, params.background, params.threads);
        buffers = new RenderBuffers(device);
index 4d5cf4340988a874873877834b6374234eb028fe..ca775939c094136b981e081d9af3afff7f260d72 100644 (file)
@@ -58,7 +58,7 @@ public:
                background = false;
                output_path = "";
 
-               progressive = false;
+               progressive = true;
                passes = INT_MAX;
                tile_size = 64;
                min_size = 64;
index da52eaecc18ea37396003b5bf0526cacd7257708..c4188fda421ac7f731d2dfc2d42f60bffbfd9d97 100644 (file)
@@ -105,6 +105,7 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man
        current_type = SHADER_TYPE_SURFACE;
        current_shader = NULL;
        background = false;
+       mix_weight_offset = SVM_STACK_INVALID;
 }
 
 int SVMCompiler::stack_size(ShaderSocketType type)
@@ -419,6 +420,84 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*> done, Stac
        }
 }
 
+void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset)
+{
+       /* todo: the weaks point here is that unlike the single closure sampling 
+          we will evaluate all nodes even if they are used as input for closures
+          that are unused. it's not clear what would be the best way to skip such
+          nodes at runtime, especially if they are tangled up  */
+
+       if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
+               ShaderInput *fin = node->input("Fac");
+               ShaderInput *cl1in = node->input("Closure1");
+               ShaderInput *cl2in = node->input("Closure2");
+
+               uint out1_offset = SVM_STACK_INVALID;
+               uint out2_offset = SVM_STACK_INVALID;
+
+               if(fin) {
+                       /* mix closure */
+                       set<ShaderNode*> dependencies;
+                       find_dependencies(dependencies, done, fin);
+                       generate_svm_nodes(dependencies, done);
+
+                       stack_assign(fin);
+
+                       if(cl1in->link)
+                               out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
+                       if(cl2in->link)
+                               out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
+
+                       add_node(NODE_MIX_CLOSURE, 
+                               encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset));
+               }
+               else {
+                       /* add closure */
+                       out1_offset = in_offset;
+                       out2_offset = in_offset;
+               }
+
+               if(cl1in->link) {
+                       generate_multi_closure(cl1in->link->parent, done, out1_offset);
+
+                       if(fin)
+                               active_stack.users[out1_offset]--;
+               }
+
+               if(cl2in->link) {
+                       generate_multi_closure(cl2in->link->parent, done, out2_offset);
+
+                       if(fin)
+                               active_stack.users[out2_offset]--;
+               }
+       }
+       else {
+               /* execute dependencies for closure */
+               foreach(ShaderInput *in, node->inputs) {
+                       if(!node_skip_input(node, in) && in->link) {
+                               set<ShaderNode*> dependencies;
+                               find_dependencies(dependencies, done, in);
+                               generate_svm_nodes(dependencies, done);
+                       }
+               }
+
+               mix_weight_offset = in_offset;
+
+               /* compile closure itself */
+               node->compile(*this);
+               stack_clear_users(node, done);
+               stack_clear_temporary(node);
+
+               mix_weight_offset = SVM_STACK_INVALID;
+
+               if(node->name == ustring("emission"))
+                       current_shader->has_surface_emission = true;
+
+               /* end node is added outside of this */
+       }
+}
+
+
 void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
 {
        /* Converting a shader graph into svm_nodes that can be executed
@@ -464,21 +543,35 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
        }
 
        if(clin->link) {
+               bool generate = false;
                if(type == SHADER_TYPE_SURFACE) {
                        /* generate surface shader */
-                       generate_closure(clin->link->parent, set<ShaderNode*>(), Stack());
+                       generate = true;
                        shader->has_surface = true;
                }
                else if(type == SHADER_TYPE_VOLUME) {
                        /* generate volume shader */
-                       generate_closure(clin->link->parent, set<ShaderNode*>(), Stack());
+                       generate = true;
                        shader->has_volume = true;
                }
                else if(type == SHADER_TYPE_DISPLACEMENT) {
                        /* generate displacement shader */
-                       generate_closure(clin->link->parent, set<ShaderNode*>(), Stack());
+                       generate = true;
                        shader->has_displacement = true;
                }
+
+               if(generate) {
+                       set<ShaderNode*> done;
+                       bool multi_closure = false; /* __MULTI_CLOSURE__ */
+
+                       if(multi_closure) {
+                               generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID);
+                       }
+                       else {
+                               Stack stack;
+                               generate_closure(clin->link->parent, done, stack);
+                       }
+               }
        }
 
        /* compile output node */
index f76649e4a6f67ff8ab613ae5c11831b875f59dab..05fb85b057ff2ab031733cbc4cbb82a4d9287cd0 100644 (file)
@@ -24,6 +24,7 @@
 #include "shader.h"
 
 #include "util_set.h"
+#include "util_string.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -65,6 +66,7 @@ public:
        uint attribute(ustring name);
        uint attribute(Attribute::Standard std);
        uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
+       uint closure_mix_weight_offset() { return mix_weight_offset; }
 
        ShaderType output_type() { return current_type; }
 
@@ -75,6 +77,8 @@ public:
 
 protected:
        struct Stack {
+               Stack() { memset(users, 0, sizeof(users)); }
+
                int users[SVM_STACK_SIZE];
        };
 
@@ -88,6 +92,7 @@ protected:
        void find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input);
        void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done);
        void generate_closure(ShaderNode *node, set<ShaderNode*> done, Stack stack);
+       void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset);
 
        void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
 
@@ -96,6 +101,7 @@ protected:
        Shader *current_shader;
        Stack active_stack;
        int max_stack_use;
+       uint mix_weight_offset;
 };
 
 CCL_NAMESPACE_END
index 450090c42f83a5ea69c6b8d617288571de8fbecd..61f3af7aa101723a47a2ba642576fd8e71b0f9ef 100644 (file)
@@ -96,7 +96,7 @@ void TileManager::set_tiles()
 
 bool TileManager::done()
 {
-       return (state.pass+1 >= passes);
+       return (state.pass+1 >= passes && state.resolution == 1);
 }
 
 bool TileManager::next()
index 90093e32d58d30cdc0fcb48362c5a974562b921d..d3f739e19f6fabd1fca19936080a23e8c886de6c 100644 (file)
@@ -109,11 +109,16 @@ string path_files_md5_hash(const string& dir)
        return hash.get_hex();
 }
 
-bool path_write_binary(const string& path, const vector<uint8_t>& binary)
+void path_create_directories(const string& path)
 {
-       /* write binary file from memory */
        boost::filesystem::create_directories(path_dirname(path));
+}
 
+bool path_write_binary(const string& path, const vector<uint8_t>& binary)
+{
+       path_create_directories(path);
+
+       /* write binary file from memory */
        FILE *f = fopen(path.c_str(), "wb");
 
        if(!f)
index a91b91461fad41c88fe2c2ed6165e19f780c630c..4a9d45ec5940b934f7d9e588359e4b1918a77950 100644 (file)
@@ -42,6 +42,7 @@ string path_escape(const string& path);
 bool path_exists(const string& path);
 string path_files_md5_hash(const string& dir);
 
+void path_create_directories(const string& path);
 bool path_write_binary(const string& path, const vector<uint8_t>& binary);
 bool path_read_binary(const string& path, vector<uint8_t>& binary);