Cycles:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 1 Sep 2011 15:53:36 +0000 (15:53 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 1 Sep 2011 15:53:36 +0000 (15:53 +0000)
* Add max diffuse/glossy/transmission bounces
* Add separate min/max for transparent depth
* Updated/added some presets that use these options
* Add ray visibility options for objects, to hide them from
  camera/diffuse/glossy/transmission/shadow rays
* Is singular ray output for light path node

Details here:
http://wiki.blender.org/index.php/Dev:2.5/Source/Render/Cycles/LightPaths

35 files changed:
intern/cycles/app/cycles_xml.cpp
intern/cycles/blender/addon/presets.py
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_object.cpp
intern/cycles/blender/blender_shader.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/bvh/bvh.cpp
intern/cycles/bvh/bvh.h
intern/cycles/bvh/bvh_build.cpp
intern/cycles/bvh/bvh_node.h
intern/cycles/kernel/kernel.cpp
intern/cycles/kernel/kernel_bvh.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_textures.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/nodes/node_light_path.osl
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/svm/bsdf_transparent.h
intern/cycles/kernel/svm/svm_light_path.h
intern/cycles/kernel/svm/svm_noise.h
intern/cycles/kernel/svm/svm_texture.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/integrator.cpp
intern/cycles/render/integrator.h
intern/cycles/render/mesh.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/object.cpp
intern/cycles/render/object.h
intern/cycles/render/scene.h
release/scripts/presets/cycles/integrator/direct_light.py
release/scripts/presets/cycles/integrator/full_global_illumination.py [new file with mode: 0644]
release/scripts/presets/cycles/integrator/limited_global_illumination.py [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_bsdf_glass.c
source/blender/nodes/intern/SHD_nodes/SHD_light_path.c

index 0e80cd80ece1cae6ec435ffb0bdd3f5676359112..7c3fb0b36257c189776a0dd7041548e4fd4771f1 100644 (file)
@@ -255,8 +255,8 @@ static void xml_read_integrator(const XMLReadState& state, pugi::xml_node node)
 {
        Integrator *integrator = state.scene->integrator;
 
-       xml_read_int(&integrator->minbounce, node, "min_bounce");
-       xml_read_int(&integrator->maxbounce, node, "max_bounce");
+       xml_read_int(&integrator->min_bounce, node, "min_bounce");
+       xml_read_int(&integrator->max_bounce, node, "max_bounce");
        xml_read_bool(&integrator->no_caustics, node, "no_caustics");
        xml_read_float(&integrator->blur_caustics, node, "blur_caustics");
 }
index 983d6dd471cc39605d6f16fee9f1f3dd7dfd06af..e5243b633be62dc276ce73b1d62b2e441d566fb3 100644 (file)
@@ -33,6 +33,11 @@ class AddPresetIntegrator(AddPresetBase, Operator):
         "cycles.max_bounces",
         "cycles.min_bounces",
         "cycles.no_caustics",
+        "cycles.diffuse_bounces",
+        "cycles.glossy_bounces",
+        "cycles.transmission_bounces",
+        "cycles.transparent_min_bounces",
+        "cycles.transparent_max_bounces"
     ]
 
     preset_subdir = "cycles/integrator"
index b2d982fdabc0dc46aa6ea64f8103f71d7529cb76..ca38520d28f7962673d28b97e46db5fbec2242f9 100644 (file)
@@ -24,7 +24,7 @@ from cycles import enums
 class CyclesRenderSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
-        bpy.types.Scene.cycles = PointerProperty(type=cls, name="Cycles Render Settings", description="Cycles Render Settings")
+        bpy.types.Scene.cycles = PointerProperty(type=cls, name="Cycles Render Settings", description="Cycles render settings")
 
         cls.device = EnumProperty(name="Device", description="Device to use for rendering",
             items=enums.devices, default="CPU")
@@ -39,18 +39,31 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
         cls.preview_pause = BoolProperty(name="Pause Preview", description="Pause all viewport preview renders",
             default=False)
 
-        cls.min_bounces = IntProperty(name="Min Bounces", description="Minimum number of bounces",
-            default=3, min=0, max=1024)
-        cls.max_bounces = IntProperty(name="Max Bounces", description="Maximum number of bounces",
-            default=8, min=0, max=1024)
         cls.no_caustics = BoolProperty(name="No Caustics", description="Leave out caustics, resulting in a darker image with less noise",
             default=False)
         cls.blur_caustics = FloatProperty(name="Blur Caustics", description="Blur caustics to reduce noise",
             default=0.0, min=0.0, max=1.0)
 
-        cls.exposure = FloatProperty(name="Exposure", description="Image brightness scale",
+        cls.min_bounces = IntProperty(name="Min Bounces", description="Minimum number of bounces, setting this lower than the maximum enables probalistic path termination (faster but noisier)",
+            default=3, min=0, max=1024)
+        cls.max_bounces = IntProperty(name="Max Bounces", description="Total maximum number of bounces",
+            default=8, min=0, max=1024)
+
+        cls.diffuse_bounces = IntProperty(name="Diffuse Bounces", description="Maximum number of diffuse reflection bounces, bounded by total maximum",
+            default=1024, min=0, max=1024)
+        cls.glossy_bounces = IntProperty(name="Glossy Bounces", description="Maximum number of glossy reflection bounces, bounded by total maximum",
+            default=1024, min=0, max=1024)
+        cls.transmission_bounces = IntProperty(name="Transmission Bounces", description="Maximum number of transmission bounces, bounded by total maximum",
+            default=1024, min=0, max=1024)
+
+        cls.transparent_min_bounces = IntProperty(name="Transparent Min Bounces", description="Minimum number of transparent bounces, setting this lower than the maximum enables probalistic path termination (faster but noisier)",
+            default=8, min=0, max=1024)
+        cls.transparent_max_bounces = IntProperty(name="Transparent Max Bounces", description="Maximum number of transparent bounces",
+            default=8, min=0, max=1024)
+
+        cls.film_exposure = FloatProperty(name="Exposure", description="Image brightness scale",
             default=1.0, min=0.0, max=10.0)
-        cls.transparent = BoolProperty(name="Transparent", description="World background is transparent",
+        cls.film_transparent = BoolProperty(name="Transparent", description="World background is transparent",
             default=False)
 
         cls.filter_type = EnumProperty(name="Filter Type", description="Pixel filter type",
@@ -81,7 +94,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
 class CyclesCameraSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
-        bpy.types.Camera.cycles = PointerProperty(type=cls, name="Cycles Camera Settings", description="Cycles Camera Settings")
+        bpy.types.Camera.cycles = PointerProperty(type=cls, name="Cycles Camera Settings", description="Cycles camera settings")
 
         cls.lens_radius = FloatProperty(name="Lens radius", description="Lens radius for depth of field",
             default=0.0, min=0.0, max=10.0)
@@ -93,7 +106,7 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
 class CyclesMaterialSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
-        bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles Material Settings")
+        bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles material settings")
 
     @classmethod
     def unregister(cls):
@@ -102,18 +115,33 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
 class CyclesWorldSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
-        bpy.types.World.cycles = PointerProperty(type=cls, name="Cycles World Settings", description="Cycles World Settings")
+        bpy.types.World.cycles = PointerProperty(type=cls, name="Cycles World Settings", description="Cycles world settings")
 
     @classmethod
     def unregister(cls):
         del bpy.types.World.cycles
 
+class CyclesVisibilitySettings(bpy.types.PropertyGroup):
+    @classmethod
+    def register(cls):
+        bpy.types.Object.cycles_visibility = PointerProperty(type=cls, name="Cycles Visibility Settings", description="Cycles visibility settings")
+
+        cls.camera = BoolProperty(name="Camera", description="Object visibility for camera rays", default=True)
+        cls.diffuse = BoolProperty(name="Diffuse", description="Object visibility for diffuse reflection rays", default=True)
+        cls.glossy = BoolProperty(name="Glossy", description="Object visibility for glossy reflection rays", default=True)
+        cls.transmission = BoolProperty(name="Transmission", description="Object visibility for transmission rays", default=True)
+        cls.shadow = BoolProperty(name="Shadow", description="Object visibility for shadow rays", default=True)
+
+    @classmethod
+    def unregister(cls):
+        del bpy.types.Object.cycles_visibility
+
 class CyclesMeshSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
-        bpy.types.Mesh.cycles = PointerProperty(type=cls, name="Cycles Mesh Settings", description="Cycles Mesh Settings")
-        bpy.types.Curve.cycles = PointerProperty(type=cls, name="Cycles Mesh Settings", description="Cycles Mesh Settings")
-        bpy.types.MetaBall.cycles = PointerProperty(type=cls, name="Cycles Mesh Settings", description="Cycles Mesh Settings")
+        bpy.types.Mesh.cycles = PointerProperty(type=cls, name="Cycles Mesh Settings", description="Cycles mesh settings")
+        bpy.types.Curve.cycles = PointerProperty(type=cls, name="Cycles Mesh Settings", description="Cycles mesh settings")
+        bpy.types.MetaBall.cycles = PointerProperty(type=cls, name="Cycles Mesh Settings", description="Cycles mesh settings")
 
         cls.displacement_method = EnumProperty(name="Displacement Method", description="Method to use for the displacement",
             items=enums.displacement_methods, default="BUMP")
@@ -124,12 +152,15 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
     @classmethod
     def unregister(cls):
         del bpy.types.Mesh.cycles
+        del bpy.types.Curve.cycles
+        del bpy.types.MetaBall.cycles
 
 def register():
     bpy.utils.register_class(CyclesRenderSettings)
     bpy.utils.register_class(CyclesCameraSettings)
     bpy.utils.register_class(CyclesMaterialSettings)
     bpy.utils.register_class(CyclesWorldSettings)
+    bpy.utils.register_class(CyclesVisibilitySettings)
     bpy.utils.register_class(CyclesMeshSettings)
     
 def unregister():
@@ -138,4 +169,5 @@ def unregister():
     bpy.utils.unregister_class(CyclesMaterialSettings)
     bpy.utils.unregister_class(CyclesWorldSettings)
     bpy.utils.unregister_class(CyclesMeshSettings)
+    bpy.utils.unregister_class(CyclesVisibilitySettings)
 
index dc102b97db816b5b9a63373fae30d281448c8660..001aacea3eb07f4e811a49c3e4f00665fc3cfc19 100644 (file)
@@ -42,6 +42,7 @@ class CyclesButtonsPanel():
 
 class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
     bl_label = "Integrator"
+    bl_options = {'DEFAULT_CLOSED'}
 
     def draw(self, context):
         layout = self.layout
@@ -58,14 +59,28 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
 
         col = split.column()
         sub = col.column(align=True)
-        sub.prop(cscene, "passes", text="Render Passes")
-        sub.prop(cscene, "preview_passes")
-        col.prop(cscene, "no_caustics")
+        sub.label(text="Passes:")
+        sub.prop(cscene, "passes", text="Render")
+        sub.prop(cscene, "preview_passes", text="Preview")
+
+        sub = col.column(align=True)
+        sub.label("Tranparency:")
+        sub.prop(cscene, "transparent_max_bounces", text="Max")
+        sub.prop(cscene, "transparent_min_bounces", text="Min")
+        sub.prop(cscene, "no_caustics")
 
         col = split.column()
+
+        sub = col.column(align=True)
+        sub.label(text="Bounces:")
+        sub.prop(cscene, "max_bounces", text="Max")
+        sub.prop(cscene, "min_bounces", text="Min")
+
         sub = col.column(align=True)
-        sub.prop(cscene, "max_bounces")
-        sub.prop(cscene, "min_bounces")
+        sub.label(text="Light Paths:")
+        sub.prop(cscene, "diffuse_bounces", text="Diffuse")
+        sub.prop(cscene, "glossy_bounces", text="Glossy")
+        sub.prop(cscene, "transmission_bounces", text="Transmission")
 
         #row = col.row()
         #row.prop(cscene, "blur_caustics")
@@ -83,8 +98,8 @@ class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
         split = layout.split()
 
         col = split.column();
-        col.prop(cscene, "exposure")
-        col.prop(cscene, "transparent")
+        col.prop(cscene, "film_exposure")
+        col.prop(cscene, "film_transparent")
 
         col = split.column()
         sub = col.column(align=True)
@@ -233,6 +248,33 @@ class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
         layout.prop(cdata, "use_subdivision");
         layout.prop(cdata, "dicing_rate");
 
+class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
+    bl_label = "Ray Visibility"
+    bl_context = "object"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        ob = context.object
+        return ob and ob.type in ('MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META') # todo: 'LAMP'
+
+    def draw(self, context):
+        layout = self.layout
+
+        ob = context.object
+        visibility = ob.cycles_visibility
+
+        split = layout.split()
+
+        col = split.column()
+        col.prop(visibility, "camera")
+        col.prop(visibility, "diffuse")
+        col.prop(visibility, "glossy")
+
+        col = split.column()
+        col.prop(visibility, "transmission")
+        col.prop(visibility, "shadow")
+
 def find_node(material, nodetype):
     if material and material.node_tree:
         ntree = material.node_tree
index 52081cc0b60f8dc44bb8cc433c03686f4d378286..f1ba2dba2f5e4d0d1465f63dbaa190cb31c201b2 100644 (file)
@@ -63,6 +63,20 @@ bool BlenderSync::object_is_light(BL::Object b_ob)
        return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
 }
 
+static uint object_ray_visibility(BL::Object b_ob)
+{
+       PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
+       uint flag = 0;
+
+       flag |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
+       flag |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
+       flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
+       flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
+       flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0;
+
+       return flag;
+}
+
 /* Light */
 
 void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
@@ -115,6 +129,11 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
        if(object_map.sync(&object, b_ob, b_parent, key)) {
                object->name = b_ob.name();
                object->tfm = tfm;
+               
+               object->visibility = object_ray_visibility(b_ob);
+               if(b_parent.ptr.data != b_ob.ptr.data)
+                       object->visibility &= object_ray_visibility(b_parent);
+
                object->tag_update(scene);
                object_updated = true;
        }
index 9024de092b72eaee529b6ffd71820c83926d19fa..4e19ee82f7796c60396ac943a7474c20ccd51f59 100644 (file)
@@ -599,7 +599,7 @@ void BlenderSync::sync_world()
        }
 
        PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-       background->transparent = get_boolean(cscene, "transparent");
+       background->transparent = get_boolean(cscene, "film_transparent");
 
        if(background->modified(prevbackground))
                background->tag_update(scene);
index c579253336f3a41f53d9bbe6ec7b2fa30e2c5522..40ec4838dad4b9b260e75f34d051003ce4096462 100644 (file)
@@ -131,8 +131,16 @@ void BlenderSync::sync_integrator()
        Integrator *integrator = scene->integrator;
        Integrator previntegrator = *integrator;
 
-       integrator->minbounce = get_int(cscene, "min_bounces");
-       integrator->maxbounce = get_int(cscene, "max_bounces");
+       integrator->min_bounce = get_int(cscene, "min_bounces");
+       integrator->max_bounce = get_int(cscene, "max_bounces");
+
+       integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
+       integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
+       integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
+
+       integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
+       integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
+
        integrator->no_caustics = get_boolean(cscene, "no_caustics");
        integrator->blur_caustics = get_float(cscene, "blur_caustics");
 
@@ -149,7 +157,7 @@ void BlenderSync::sync_film()
        Film *film = scene->film;
        Film prevfilm = *film;
 
-       film->exposure = get_float(cscene, "exposure");
+       film->exposure = get_float(cscene, "film_exposure");
 
        if(film->modified(prevfilm))
                film->tag_update(scene);
index 664bdd98b1f67b9779f141581178e4e47fed54b2..9bd748157bfdf90b0648681655875eaa363fc2f8 100644 (file)
@@ -84,6 +84,7 @@ bool BVH::cache_read(CacheData& key)
                value.read(pack.nodes);
                value.read(pack.object_node);
                value.read(pack.tri_woop);
+               value.read(pack.prim_visibility);
                value.read(pack.prim_index);
                value.read(pack.prim_object);
                value.read(pack.is_leaf);
@@ -103,6 +104,7 @@ void BVH::cache_write(CacheData& key)
        value.add(pack.nodes);
        value.add(pack.object_node);
        value.add(pack.tri_woop);
+       value.add(pack.prim_visibility);
        value.add(pack.prim_index);
        value.add(pack.prim_object);
        value.add(pack.is_leaf);
@@ -236,6 +238,8 @@ void BVH::pack_triangles()
 
        pack.tri_woop.clear();
        pack.tri_woop.resize(tidx_size * nsize);
+       pack.prim_visibility.clear();
+       pack.prim_visibility.resize(tidx_size);
 
        for(unsigned int i = 0; i < tidx_size; i++) {
                if(pack.prim_index[i] != -1) {
@@ -243,6 +247,10 @@ void BVH::pack_triangles()
 
                        pack_triangle(i, woop);
                        memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
+
+                       int tob = pack.prim_object[i];
+                       Object *ob = objects[tob];
+                       pack.prim_visibility[i] = ob->visibility;
                }
        }
 }
@@ -292,12 +300,14 @@ void BVH::pack_instances(size_t nodes_size)
 
        pack.prim_index.resize(prim_index_size);
        pack.prim_object.resize(prim_index_size);
+       pack.prim_visibility.resize(prim_index_size);
        pack.tri_woop.resize(tri_woop_size);
        pack.nodes.resize(nodes_size);
        pack.object_node.resize(objects.size());
 
        int *pack_prim_index = &pack.prim_index[0];
        int *pack_prim_object = &pack.prim_object[0];
+       uint *pack_prim_visibility = &pack.prim_visibility[0];
        float4 *pack_tri_woop = &pack.tri_woop[0];
        int4 *pack_nodes = &pack.nodes[0];
 
@@ -327,9 +337,11 @@ void BVH::pack_instances(size_t nodes_size)
                {
                        size_t bvh_prim_index_size = bvh->pack.prim_index.size();
                        int *bvh_prim_index = &bvh->pack.prim_index[0];
+                       uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
 
                        for(size_t i = 0; i < bvh_prim_index_size; i++) {
                                pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+                               pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i] + mesh_tri_offset;
                                pack_prim_object[pack_prim_index_offset] = 0;  // unused for instances
                                pack_prim_index_offset++;
                        }
@@ -394,25 +406,25 @@ void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
 {
        if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1)
                /* object */
-               pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0);
+               pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility);
        else
                /* triangle */
-               pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi);
+               pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility);
 }
 
 void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
 {
-       pack_node(e.idx, e0.node->m_bounds, e1.node->m_bounds, e0.encodeIdx(), e1.encodeIdx());
+       pack_node(e.idx, e0.node->m_bounds, e1.node->m_bounds, e0.encodeIdx(), e1.encodeIdx(), e0.node->m_visibility, e1.node->m_visibility);
 }
 
-void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1)
+void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1, uint visibility0, uint visibility1)
 {
        int4 data[BVH_NODE_SIZE] =
        {
                make_int4(__float_as_int(b0.min.x), __float_as_int(b0.max.x), __float_as_int(b0.min.y), __float_as_int(b0.max.y)),
                make_int4(__float_as_int(b1.min.x), __float_as_int(b1.max.x), __float_as_int(b1.min.y), __float_as_int(b1.max.y)),
                make_int4(__float_as_int(b0.min.z), __float_as_int(b0.max.z), __float_as_int(b1.min.z), __float_as_int(b1.max.z)),
-               make_int4(c0, c1, 0, 0)
+               make_int4(c0, c1, visibility0, visibility1)
        };
 
        memcpy(&pack.nodes[idx * BVH_NODE_SIZE], data, sizeof(int4)*BVH_NODE_SIZE);
@@ -467,10 +479,11 @@ void RegularBVH::refit_nodes()
        assert(!params.top_level);
 
        BoundBox bbox;
-       refit_node(0, (pack.is_leaf[0])? true: false, bbox);
+       uint visibility = 0;
+       refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility);
 }
 
-void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox)
+void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
 {
        int4 *data = &pack.nodes[idx*4];
 
@@ -499,21 +512,25 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox)
                                bbox.grow(vpos[vidx[1]]);
                                bbox.grow(vpos[vidx[2]]);
                        }
+
+                       visibility |= ob->visibility;
                }
 
-               pack_node(idx, bbox, bbox, c0, c1);
+               pack_node(idx, bbox, bbox, c0, c1, visibility, visibility);
        }
        else {
                /* refit inner node, set bbox from children */
                BoundBox bbox0, bbox1;
+               uint visibility0 = 0, visibility1 = 0;
 
-               refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0);
-               refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1);
+               refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0);
+               refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1, visibility1);
+
+               pack_node(idx, bbox0, bbox1, c0, c1, visibility0, visibility1);
 
                bbox.grow(bbox0);
                bbox.grow(bbox1);
-
-               pack_node(idx, bbox0, bbox1, c0, c1);
+               visibility = visibility0|visibility1;
        }
 }
 
@@ -523,6 +540,8 @@ QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_)
 : BVH(params_, objects_)
 {
        params.use_qbvh = true;
+
+       /* todo: use visibility */
 }
 
 void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
index 79e46d6a13c1f321281cae40f2ce6351d3d12798..e502af7233525dfbbd4f6b3b0411f9cd2fc492a5 100644 (file)
@@ -51,6 +51,8 @@ struct PackedBVH {
        array<int> object_node; 
        /* precomputed triangle intersection data, one triangle is 4x float4 */
        array<float4> tri_woop; 
+       /* visibility visibilitys for primitives */
+       array<uint> prim_visibility;
        /* mapping from BVH primitive index to true primitive index, as primitives
           may be duplicated due to spatial splits. -1 for instances. */
        array<int> prim_index;
@@ -121,11 +123,11 @@ protected:
        void pack_nodes(const array<int>& prims, const BVHNode *root);
        void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
        void pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1);
-       void pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1);
+       void pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1, uint visibility0, uint visibility1);
 
        /* refit */
        void refit_nodes();
-       void refit_node(int idx, bool leaf, BoundBox& bbox);
+       void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
 };
 
 /* QBVH
index 3e47cb75014e4b6169d402019ec986d70422f791..d3e84e11d53807653cb94a7b8003438deedc1514 100644 (file)
@@ -218,12 +218,13 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const Reference *ref, int num)
 {
        if(num == 0) {
                BoundBox bounds;
-               return new LeafNode(bounds, 0, 0);
+               return new LeafNode(bounds, 0, 0, 0);
        }
        else if(num == 1) {
                prim_index.push_back(ref[0].prim_index);
                prim_object.push_back(ref[0].prim_object);
-               return new LeafNode(ref[0].bounds, prim_index.size()-1, prim_index.size());
+               uint visibility = objects[ref[0].prim_object]->visibility;
+               return new LeafNode(ref[0].bounds, visibility, prim_index.size()-1, prim_index.size());
        }
        else {
                int mid = num/2;
@@ -244,12 +245,14 @@ BVHNode* BVHBuild::create_leaf_node(const NodeSpec& spec)
        vector<int>& p_object = prim_object;
        BoundBox bounds;
        int num = 0;
+       uint visibility = 0;
 
        for(int i = 0; i < spec.num; i++) {
                if(references.back().prim_index != -1) {
                        p_index.push_back(references.back().prim_index);
                        p_object.push_back(references.back().prim_object);
                        bounds.grow(references.back().bounds);
+                       visibility |= objects[references.back().prim_object]->visibility;
                        references.pop_back();
                        num++;
                }
@@ -258,7 +261,7 @@ BVHNode* BVHBuild::create_leaf_node(const NodeSpec& spec)
        BVHNode *leaf = NULL;
        
        if(num > 0) {
-               leaf = new LeafNode(bounds, p_index.size() - num, p_index.size());
+               leaf = new LeafNode(bounds, visibility, p_index.size() - num, p_index.size());
 
                if(num == spec.num)
                        return leaf;
index f8f0ffecd9530e4928d38917bf5f87bf925f3d99..5e0a17a11936f8d0cf30b6552740d195c97eabf6 100644 (file)
@@ -52,6 +52,7 @@ public:
        float getArea() const { return m_bounds.area(); }
 
        BoundBox m_bounds;
+       uint m_visibility;
 
        // Subtree functions
        int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const;
@@ -65,6 +66,7 @@ public:
        InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1)
        {
                m_bounds = bounds;
+               m_visibility = child0->m_visibility|child1->m_visibility;
                children[0] = child0;
                children[1] = child1;
        }
@@ -80,9 +82,10 @@ public:
 class LeafNode : public BVHNode
 {
 public:
-       LeafNode(const BoundBox& bounds, int lo, int hi) 
+       LeafNode(const BoundBox& bounds, uint visibility, int lo, int hi) 
        {
                m_bounds = bounds;
+               m_visibility = visibility;
                m_lo = lo;
                m_hi = hi;
        }
index d9ba237d964830a3b2e9311d68d28c9d428a8eaa..01682d11f33f5d9a952b777712163ecac7a17591 100644 (file)
@@ -89,6 +89,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
                kg->__tri_woop.data = (float4*)mem;
                kg->__tri_woop.width = width;
        }
+       else if(strcmp(name, "__prim_visibility") == 0) {
+               kg->__prim_visibility.data = (uint*)mem;
+               kg->__prim_visibility.width = width;
+       }
        else if(strcmp(name, "__prim_index") == 0) {
                kg->__prim_index.data = (uint*)mem;
                kg->__prim_index.width = width;
index 4dea540e31cb45417a828c53a390db09d6204cb3..df7663b5555fa8b0edf3d37366f08f16fe05a5ef 100644 (file)
@@ -78,7 +78,7 @@ __device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *
 __device_inline void bvh_node_intersect(KernelGlobals *kg,
        bool *traverseChild0, bool *traverseChild1,
        bool *closestChild1, int *nodeAddr0, int *nodeAddr1,
-       float3 P, float3 idir, float t, int nodeAddr)
+       float3 P, float3 idir, float t, uint visibility, int nodeAddr)
 {
        /* fetch node data */
        float4 n0xy = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
@@ -111,8 +111,14 @@ __device_inline void bvh_node_intersect(KernelGlobals *kg,
        float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
 
        /* decide which nodes to traverse next */
+#ifdef __VISIBILITY_FLAG__
+       /* this visibility test gives a 5% performance hit, how to solve? */
+       *traverseChild0 = (c0max >= c0min) && (__float_as_int(cnodes.z) & visibility);
+       *traverseChild1 = (c1max >= c1min) && (__float_as_int(cnodes.w) & visibility);
+#else
        *traverseChild0 = (c0max >= c0min);
        *traverseChild1 = (c1max >= c1min);
+#endif
 
        *nodeAddr0 = __float_as_int(cnodes.x);
        *nodeAddr1 = __float_as_int(cnodes.y);
@@ -121,7 +127,8 @@ __device_inline void bvh_node_intersect(KernelGlobals *kg,
 }
 
 /* Sven Woop's algorithm */
-__device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, int object, int triAddr)
+__device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *isect,
+       float3 P, float3 idir, uint visibility, int object, int triAddr)
 {
        /* compute and check intersection t-value */
        float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
@@ -146,18 +153,25 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise
                        float v = Oy + t*Dy;
 
                        if(v >= 0.0f && u + v <= 1.0f) {
-                               /* record intersection */
-                               isect->prim = triAddr;
-                               isect->object = object;
-                               isect->u = u;
-                               isect->v = v;
-                               isect->t = t;
+#ifdef __VISIBILITY_FLAG__
+                               /* visibility flag test. we do it here under the assumption
+                                  that most triangles are culled by node flags */
+                               if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
+#endif
+                               {
+                                       /* record intersection */
+                                       isect->prim = triAddr;
+                                       isect->object = object;
+                                       isect->u = u;
+                                       isect->v = v;
+                                       isect->t = t;
+                               }
                        }
                }
        }
 }
 
-__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const bool isshadowray, Intersection *isect)
+__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
 {
        /* traversal stack in CUDA thread-local memory */
        int traversalStack[BVH_STACK_SIZE];
@@ -191,7 +205,7 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const bo
 
                                bvh_node_intersect(kg, &traverseChild0, &traverseChild1,
                                        &closestChild1, &nodeAddr, &nodeAddrChild1,
-                                       P, idir, isect->t, nodeAddr);
+                                       P, idir, isect->t, visibility, nodeAddr);
 
                                if(traverseChild0 != traverseChild1) {
                                        /* one child was intersected */
@@ -236,10 +250,10 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const bo
                                        /* triangle intersection */
                                        while(primAddr < primAddr2) {
                                                /* intersect ray against triangle */
-                                               bvh_triangle_intersect(kg, isect, P, idir, object, primAddr);
+                                               bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
 
                                                /* shadow ray early termination */
-                                               if(isshadowray && isect->prim != ~0)
+                                               if(visibility == PATH_RAY_SHADOW && isect->prim != ~0)
                                                        return true;
 
                                                primAddr++;
index d4ed4651751680367ac85b55e2c6bfdbbb09580d..7f7aaad3270378e43b44d647daf5753587a31d15 100644 (file)
@@ -58,51 +58,108 @@ __device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global f
 }
 #endif
 
-__device float path_terminate_probability(KernelGlobals *kg, int bounce, const float3 throughput)
-{
-       if(bounce >= kernel_data.integrator.maxbounce)
-               return 0.0f;
-       else if(bounce <= kernel_data.integrator.minbounce)
-               return 1.0f;
+typedef struct PathState {
+       uint flag;
+       int bounce;
 
-       return average(throughput);
+       int diffuse_bounce;
+       int glossy_bounce;
+       int transmission_bounce;
+       int transparent_bounce;
+} PathState;
+
+__device_inline void path_state_init(PathState *state)
+{
+       state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR;
+       state->bounce = 0;
+       state->diffuse_bounce = 0;
+       state->glossy_bounce = 0;
+       state->transmission_bounce = 0;
+       state->transparent_bounce = 0;
 }
 
-__device int path_flag_from_label(int path_flag, int label)
+__device_inline void path_state_next(PathState *state, int label)
 {
-       /* reflect/transmit */
+       /* ray through transparent keeps same flags from previous ray and is
+          not counted as a regular bounce, transparent has separate max */
+       if(label & LABEL_TRANSPARENT) {
+               state->flag |= PATH_RAY_TRANSPARENT;
+               state->transparent_bounce++;
+
+               return;
+       }
+
+       state->bounce++;
+
+       /* reflection/transmission */
        if(label & LABEL_REFLECT) {
-               path_flag |= PATH_RAY_REFLECT;
-               path_flag &= ~PATH_RAY_TRANSMIT;
+               state->flag |= PATH_RAY_REFLECT;
+               state->flag &= ~(PATH_RAY_TRANSMIT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
+
+               if(label & LABEL_DIFFUSE)
+                       state->diffuse_bounce++;
+               else
+                       state->glossy_bounce++;
        }
        else {
                kernel_assert(label & LABEL_TRANSMIT);
 
-               path_flag |= PATH_RAY_TRANSMIT;
-               path_flag &= ~PATH_RAY_REFLECT;
+               state->flag |= PATH_RAY_TRANSMIT;
+               state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
+
+               state->transmission_bounce++;
        }
 
        /* diffuse/glossy/singular */
        if(label & LABEL_DIFFUSE) {
-               path_flag |= PATH_RAY_DIFFUSE;
-               path_flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR);
+               state->flag |= PATH_RAY_DIFFUSE;
+               state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR);
        }
        else if(label & LABEL_GLOSSY) {
-               path_flag |= PATH_RAY_GLOSSY;
-               path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR);
+               state->flag |= PATH_RAY_GLOSSY;
+               state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR);
        }
        else {
-               kernel_assert(label & (LABEL_SINGULAR|LABEL_STRAIGHT));
+               kernel_assert(label & LABEL_SINGULAR);
+
+               state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR;
+               state->flag &= ~PATH_RAY_DIFFUSE;
+       }
+}
+
+__device_inline uint path_state_ray_visibility(PathState *state)
+{
+       uint flag = state->flag;
+
+       /* for visibility, diffuse/glossy are for reflection only */
+       if(flag & PATH_RAY_TRANSMIT)
+               flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
 
-               path_flag |= PATH_RAY_SINGULAR;
-               path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
+       return flag;
+}
+
+__device_inline float path_state_terminate_probability(KernelGlobals *kg, PathState *state, const float3 throughput)
+{
+       if(state->flag & PATH_RAY_TRANSPARENT) {
+               /* transparent rays treated separately */
+               if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
+                       return 0.0f;
+               else if(state->transparent_bounce <= kernel_data.integrator.transparent_min_bounce)
+                       return 1.0f;
        }
-       
-       /* ray through transparent is still camera ray */
-       if(!(label & LABEL_STRAIGHT))
-               path_flag &= ~PATH_RAY_CAMERA;
-       
-       return path_flag;
+       else {
+               /* other rays */
+               if((state->bounce >= kernel_data.integrator.max_bounce) ||
+                  (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) ||
+                  (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) ||
+                  (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce))
+                       return 0.0f;
+               else if(state->bounce <= kernel_data.integrator.min_bounce)
+                       return 1.0f;
+       }
+
+       /* probalistic termination */
+       return average(throughput);
 }
 
 __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
@@ -114,24 +171,27 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
 #ifdef __EMISSION__
        float ray_pdf = 0.0f;
 #endif
-       int path_flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR;
+       PathState state;
        int rng_offset = PRNG_BASE_NUM;
 
+       path_state_init(&state);
+
        /* path iteration */
-       for(int bounce = 0; ; bounce++, rng_offset += PRNG_BOUNCE_NUM) {
+       for(;; rng_offset += PRNG_BOUNCE_NUM) {
                /* intersect scene */
                Intersection isect;
+               uint visibility = path_state_ray_visibility(&state);
 
-               if(!scene_intersect(kg, &ray, false, &isect)) {
+               if(!scene_intersect(kg, &ray, visibility, &isect)) {
                        /* eval background shader if nothing hit */
-                       if(kernel_data.background.transparent && (path_flag & PATH_RAY_CAMERA)) {
+                       if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) {
                                Ltransparent += average(throughput);
                        }
                        else {
 #ifdef __BACKGROUND__
                                ShaderData sd;
                                shader_setup_from_background(kg, &sd, &ray);
-                               L += throughput*shader_eval_background(kg, &sd, path_flag);
+                               L += throughput*shader_eval_background(kg, &sd, state.flag);
                                shader_release(kg, &sd);
 #else
                                L += make_float3(0.8f, 0.8f, 0.8f);
@@ -145,10 +205,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
                ShaderData sd;
                shader_setup_from_ray(kg, &sd, &isect, &ray);
                float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF);
-               shader_eval_surface(kg, &sd, rbsdf, path_flag);
+               shader_eval_surface(kg, &sd, rbsdf, state.flag);
 
 #ifdef __HOLDOUT__
-               if((sd.flag & SD_HOLDOUT) && (path_flag & PATH_RAY_CAMERA)) {
+               if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) {
                        float3 holdout_weight = shader_holdout_eval(kg, &sd);
 
                        if(kernel_data.background.transparent)
@@ -160,11 +220,25 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
                /* emission */
                if(kernel_data.integrator.use_emission) {
                        if(sd.flag & SD_EMISSION)
-                               L += throughput*indirect_emission(kg, &sd, isect.t, path_flag, ray_pdf);
+                               L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+               }
+#endif
+
+               /* path termination. this is a strange place to put the termination, it's
+                  mainly due to the mixed in MIS that we use. gives too many unneeded
+                  shader evaluations, only need emission if we are going to terminate */
+               float probability = path_state_terminate_probability(kg, &state, throughput);
+               float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE);
 
+               if(terminate >= probability)
+                       break;
+
+               throughput /= probability;
+
+#ifdef __EMISSION__
+               if(kernel_data.integrator.use_emission) {
                        /* sample illumination from lights to find path contribution */
-                       if((sd.flag & SD_BSDF_HAS_EVAL) &&
-                               bounce != kernel_data.integrator.maxbounce) {
+                       if(sd.flag & SD_BSDF_HAS_EVAL) {
                                float light_t = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT);
                                float light_o = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_F);
                                float light_u = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_U);
@@ -173,9 +247,11 @@ __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 */
+
                                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, true, &isect))
+                                       if(!scene_intersect(kg, &light_ray, PATH_RAY_SHADOW, &isect))
                                                L += throughput*light_L;
                                }
                        }
@@ -183,10 +259,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
 #endif
 
                /* no BSDF? we can stop here */
-               if(!(sd.flag & SD_BSDF)) {
-                       path_flag &= ~PATH_RAY_CAMERA;
+               if(!(sd.flag & SD_BSDF))
                        break;
-               }
 
                /* sample BSDF */
                float bsdf_pdf;
@@ -202,10 +276,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
 
                shader_release(kg, &sd);
 
-               if(bsdf_pdf == 0.0f || is_zero(bsdf_eval)) {
-                       path_flag &= ~PATH_RAY_CAMERA;
+               if(bsdf_pdf == 0.0f || is_zero(bsdf_eval))
                        break;
-               }
 
                /* modify throughput */
                throughput *= bsdf_eval/bsdf_pdf;
@@ -215,18 +287,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
                ray_pdf = bsdf_pdf;
 #endif
 
-               path_flag = path_flag_from_label(path_flag, label);
-
-               /* path termination */
-               float probability = path_terminate_probability(kg, bounce, throughput);
-               float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE);
-
-               if(terminate >= probability) {
-                       path_flag &= ~PATH_RAY_CAMERA;
-                       break;
-               }
-
-               throughput /= probability;
+               /* update path state */
+               path_state_next(&state, label);
 
                /* setup ray */
                ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
index dd4566ec1842125d7ef1b9d3a29958bfe42717a1..19635b2664c799ece78f320adcd0e2e18b63ea9b 100644 (file)
@@ -11,6 +11,7 @@
 /* bvh */
 KERNEL_TEX(float4, texture_float4, __bvh_nodes)
 KERNEL_TEX(float4, texture_float4, __tri_woop)
+KERNEL_TEX(uint, texture_uint, __prim_visibility)
 KERNEL_TEX(uint, texture_uint, __prim_index)
 KERNEL_TEX(uint, texture_uint, __prim_object)
 KERNEL_TEX(uint, texture_uint, __object_node)
index 06581d593e4b96b4a201dfddbd0ffc189e602f8d..5881f0909440b45bc464497e9e2b04600b6fd357 100644 (file)
@@ -34,11 +34,14 @@ CCL_NAMESPACE_BEGIN
 #define __BACKGROUND__
 #define __EMISSION__
 #define __CAUSTICS_TRICKS__
+#define __VISIBILITY_FLAG__
+
 #ifndef __KERNEL_OPENCL__
 #define __SVM__
 #define __TEXTURES__
 #define __HOLDOUT__
 #endif
+
 #define __RAY_DIFFERENTIALS__
 #define __CAMERA_CLIPPING__
 #define __INTERSECTION_REFINE__
@@ -76,7 +79,8 @@ enum PathRayFlag {
        PATH_RAY_TRANSMIT = 8,
        PATH_RAY_DIFFUSE = 16,
        PATH_RAY_GLOSSY = 32,
-       PATH_RAY_SINGULAR = 64
+       PATH_RAY_SINGULAR = 64,
+       PATH_RAY_TRANSPARENT = 128
 };
 
 /* Bidirectional Path Tracing */
@@ -115,7 +119,7 @@ typedef enum ClosureLabel {
        LABEL_DIFFUSE = 128,
        LABEL_GLOSSY = 256,
        LABEL_SINGULAR = 512,
-       LABEL_STRAIGHT = 1024,
+       LABEL_TRANSPARENT = 1024,
        LABEL_STOP = 2048
 } ClosureLabel;
 
@@ -351,9 +355,18 @@ typedef struct KernelIntegrator {
        float pdf_triangles;
        float pdf_lights;
 
-       /* path tracing */
-       int minbounce;
-       int maxbounce;
+       /* bounces */
+       int min_bounce;
+       int max_bounce;
+
+    int max_diffuse_bounce;
+    int max_glossy_bounce;
+    int max_transmission_bounce;
+
+       /* transparent */
+    int transparent_min_bounce;
+    int transparent_max_bounce;
+       int transparent_shadows;
 
        /* caustics */
        int no_caustics;
index 081640428ab905b951ebf13c3095680c7201d578..0ead20bf2bbca4c07a30771040851ceb7a8e29b7 100644 (file)
@@ -23,6 +23,7 @@ shader node_light_path(
        output float IsShadowRay = 0.0,
        output float IsDiffuseRay = 0.0,
        output float IsGlossyRay = 0.0,
+       output float IsSingularRay = 0.0,
        output float IsReflectionRay = 0.0,
        output float IsTransmissionRay = 0.0)
 {
@@ -30,6 +31,7 @@ shader node_light_path(
        IsShadowRay = raytype("shadow");
        IsDiffuseRay = raytype("diffuse");
        IsGlossyRay = raytype("glossy");
+       IsSingularRay = raytype("singular");
        IsReflectionRay = raytype("reflection");
        IsTransmissionRay = raytype("refraction");
 }
index 007d14b526b751e00423ea8e4d843ad67822ad27..73ff4f414232d207f93efc6ac2e473a6cd424b1c 100644 (file)
@@ -89,7 +89,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
        globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object);
 
        /* booleans */
-       globals->raytype = path_flag;
+       globals->raytype = path_flag; /* todo: add our own ray types */
        globals->backfacing = (sd->flag & SD_BACKFACING);
 
        /* don't know yet if we need this */
@@ -437,7 +437,7 @@ int OSLShader::bsdf_sample(const ShaderData *sd, float randu, float randv, float
                else if(uscattering == OSL::Labels::SINGULAR)
                        label |= LABEL_SINGULAR;
                else
-                       label |= LABEL_STRAIGHT;
+                       label |= LABEL_TRANSPARENT;
 
                /* eval + pdf */
                eval *= flat->weight;
index 30288bf251d81d466f3bebd3e3629fd3e9b457cf..1674f04955e7a98490d2de50fbba22a46f458d42 100644 (file)
@@ -70,7 +70,7 @@ __device int bsdf_transparent_sample(const ShaderData *sd, float randu, float ra
 #endif
        *pdf = 1;
        *eval = make_float3(1, 1, 1);
-       return LABEL_TRANSMIT|LABEL_STRAIGHT;
+       return LABEL_TRANSMIT|LABEL_TRANSPARENT;
 }
 
 CCL_NAMESPACE_END
index d6413d1569e97f6157f2ebd8317efddd2abfa33e..1b13fd93a0fb967cfb90ac04cd142b104bdb2205 100644 (file)
@@ -29,6 +29,7 @@ __device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uint
                case NODE_LP_shadow: info = (path_flag & PATH_RAY_SHADOW)? 1.0f: 0.0f; break;
                case NODE_LP_diffuse: info = (path_flag & PATH_RAY_DIFFUSE)? 1.0f: 0.0f; break;
                case NODE_LP_glossy: info = (path_flag & PATH_RAY_GLOSSY)? 1.0f: 0.0f; break;
+               case NODE_LP_singular: info = (path_flag & PATH_RAY_SINGULAR)? 1.0f: 0.0f; break;
                case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break;
                case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 1.0f: 0.0f; break;
                case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break;
index 72ff353abb4aa5669c3ff0a4f47121eb361319c1..28ad028ad0e7e45b9ef3701cd7859628bb610bb8 100644 (file)
@@ -209,22 +209,5 @@ __device float psnoise(float3 p, float3 pperiod)
        return perlin_periodic(p.x, p.y, p.z, pperiod);
 }
 
-/* turbulence */
-__device_noinline float turbulence(float3 P, int oct, bool hard)
-{
-       float amp = 1.0f, fscale = 1.0f, sum = 0.0f;
-       int i;
-
-       for(i=0; i<=oct; i++, amp *= 0.5f, fscale *= 2.0f) {
-               float t = noise(fscale*P);
-               if(hard) t = fabsf(2.0f*t - 1.0f);
-               sum += t * amp;
-       }
-
-       sum *= ((float)(1<<oct)/(float)((1<<(oct+1))-1));
-
-       return sum;
-}
-
 CCL_NAMESPACE_END
 
index 0bf0cf8c2cd8422f97073883125b76b7b8a9055b..e273a92c988824a01dfde0952048299a80f60289 100644 (file)
@@ -42,7 +42,7 @@ __device float voronoi_distance(NodeDistanceMetric distance_metric, float3 d, fl
 
 /* Voronoi / Worley like */
 
-__device void voronoi(float3 p, NodeDistanceMetric distance_metric, float e, float da[4], float3 pa[4])
+__device_noinline void voronoi(float3 p, NodeDistanceMetric distance_metric, float e, float da[4], float3 pa[4])
 {
        /* returns distances in da and point coords in pa */
        int xx, yy, zz, xi, yi, zi;
@@ -213,7 +213,7 @@ __device float noise_wave(NodeWaveType wave, float a)
 
 /* Turbulence */
 
-__device float noise_turbulence(float3 p, NodeNoiseBasis basis, int octaves, int hard)
+__device_noinline float noise_turbulence(float3 p, NodeNoiseBasis basis, int octaves, int hard)
 {
        float fscale = 1.0f;
        float amp = 1.0f;
index 786478c0c0383100c5a8cde5728dfac54b486975..758ba25c07a153aad45cb5f1abc8c787981f23c9 100644 (file)
@@ -104,6 +104,7 @@ typedef enum NodeLightPath {
        NODE_LP_shadow,
        NODE_LP_diffuse,
        NODE_LP_glossy,
+       NODE_LP_singular,
        NODE_LP_reflection,
        NODE_LP_transmission,
        NODE_LP_backfacing
index 30736670cc35c126be1f984c413c4429fbb8c1c6..57689be3965694c905c7bef805f0bb363a5b843b 100644 (file)
@@ -25,8 +25,19 @@ CCL_NAMESPACE_BEGIN
 
 Integrator::Integrator()
 {
-       minbounce = 2;
-       maxbounce = 7;
+       min_bounce = 2;
+       max_bounce = 7;
+
+       max_diffuse_bounce = max_bounce;
+       max_glossy_bounce = max_bounce;
+       max_transmission_bounce = max_bounce;
+       probalistic_termination = true;
+
+       transparent_min_bounce = min_bounce;
+       transparent_max_bounce = max_bounce;
+       transparent_probalistic = true;
+       transparent_shadows = false;
+
        no_caustics = false;
        blur_caustics = 0.0f;
 
@@ -47,13 +58,29 @@ void Integrator::device_update(Device *device, DeviceScene *dscene)
        KernelIntegrator *kintegrator = &dscene->data.integrator;
 
        /* integrator parameters */
-       kintegrator->minbounce = minbounce + 1;
-       kintegrator->maxbounce = maxbounce + 1;
+       kintegrator->max_bounce = max_bounce + 1;
+       if(probalistic_termination)
+               kintegrator->min_bounce = min_bounce + 1;
+       else
+               kintegrator->min_bounce = kintegrator->max_bounce;
+
+       kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
+       kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
+       kintegrator->max_transmission_bounce = max_transmission_bounce + 1;
+
+       kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
+       if(transparent_probalistic)
+               kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
+       else
+               kintegrator->transparent_min_bounce = kintegrator->transparent_max_bounce;
+
+       kintegrator->transparent_shadows = transparent_shadows;
+
        kintegrator->no_caustics = no_caustics;
        kintegrator->blur_caustics = blur_caustics;
 
        /* sobol directions table */
-       int dimensions = PRNG_BASE_NUM + (maxbounce + 2)*PRNG_BOUNCE_NUM;
+       int dimensions = PRNG_BASE_NUM + (max_bounce + 2)*PRNG_BOUNCE_NUM;
        uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions);
 
        sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
@@ -71,8 +98,16 @@ void Integrator::device_free(Device *device, DeviceScene *dscene)
 
 bool Integrator::modified(const Integrator& integrator)
 {
-       return !(minbounce == integrator.minbounce &&
-               maxbounce == integrator.maxbounce &&
+       return !(min_bounce == integrator.min_bounce &&
+               max_bounce == integrator.max_bounce &&
+               max_diffuse_bounce == integrator.max_diffuse_bounce &&
+               max_glossy_bounce == integrator.max_glossy_bounce &&
+               max_transmission_bounce == integrator.max_transmission_bounce &&
+               probalistic_termination == integrator.probalistic_termination &&
+               transparent_min_bounce == integrator.transparent_min_bounce &&
+               transparent_max_bounce == integrator.transparent_max_bounce &&
+               transparent_probalistic == integrator.transparent_probalistic &&
+               transparent_shadows == integrator.transparent_shadows &&
                no_caustics == integrator.no_caustics &&
                blur_caustics == integrator.blur_caustics);
 }
index b7d0c48131f300412d45ec5ef524341ae2e1850c..5bab4470089e004e53d444035551eecf35e2043b 100644 (file)
@@ -27,8 +27,19 @@ class Scene;
 
 class Integrator {
 public:
-       int minbounce;
-       int maxbounce;
+       int min_bounce;
+       int max_bounce;
+
+       int max_diffuse_bounce;
+       int max_glossy_bounce;
+       int max_transmission_bounce;
+       bool probalistic_termination;
+
+       int transparent_min_bounce;
+       int transparent_max_bounce;
+       bool transparent_probalistic;
+       bool transparent_shadows;
+
        bool no_caustics;
        float blur_caustics;
        bool need_update;
index b916330965213a8c819f5cefa1fdfaf5711cfa98..b73013fc378ca94e8e4f85a858c5846eb635a36a 100644 (file)
@@ -576,6 +576,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
                dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
                device->tex_alloc("__tri_woop", dscene->tri_woop);
        }
+       if(pack.prim_visibility.size()) {
+               dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
+               device->tex_alloc("__prim_visibility", dscene->prim_visibility);
+       }
        if(pack.prim_index.size()) {
                dscene->prim_index.reference((uint*)&pack.prim_index[0], pack.prim_index.size());
                device->tex_alloc("__prim_index", dscene->prim_index);
@@ -686,6 +690,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
        device->tex_free(dscene->bvh_nodes);
        device->tex_free(dscene->object_node);
        device->tex_free(dscene->tri_woop);
+       device->tex_free(dscene->prim_visibility);
        device->tex_free(dscene->prim_index);
        device->tex_free(dscene->prim_object);
        device->tex_free(dscene->tri_normal);
@@ -699,6 +704,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
        dscene->bvh_nodes.clear();
        dscene->object_node.clear();
        dscene->tri_woop.clear();
+       dscene->prim_visibility.clear();
        dscene->prim_index.clear();
        dscene->prim_object.clear();
        dscene->tri_normal.clear();
index 5ffc3fbbabbe17535974983e054b42bd68364999..900115d223167543842ced39f4678be9ffcf4edb 100644 (file)
@@ -1117,7 +1117,7 @@ GlassBsdfNode::GlassBsdfNode()
 {
        distribution = ustring("Sharp");
 
-       add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
+       add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
        add_input("Fresnel", SHADER_SOCKET_FLOAT, 0.3f);
 }
 
@@ -1490,8 +1490,8 @@ LightPathNode::LightPathNode()
        add_output("Is Shadow Ray", SHADER_SOCKET_FLOAT);
        add_output("Is Diffuse Ray", SHADER_SOCKET_FLOAT);
        add_output("Is Glossy Ray", SHADER_SOCKET_FLOAT);
-       add_output("Is Reflection Ray", SHADER_SOCKET_FLOAT);
        add_output("Is Transmission Ray", SHADER_SOCKET_FLOAT);
+       add_output("Is Singular Ray", SHADER_SOCKET_FLOAT);
 }
 
 void LightPathNode::compile(SVMCompiler& compiler)
@@ -1522,12 +1522,19 @@ void LightPathNode::compile(SVMCompiler& compiler)
                compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, out->stack_offset);
        }
 
+       out = output("Is Singular Ray");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, out->stack_offset);
+       }
+
        out = output("Is Reflection Ray");
        if(!out->links.empty()) {
                compiler.stack_assign(out);
                compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, out->stack_offset);
        }
 
+
        out = output("Is Transmission Ray");
        if(!out->links.empty()) {
                compiler.stack_assign(out);
index 06c93e48b897a73756a315cf333ddc2ea22cdf4c..4ba2de6e61b7877ebed326d332b45ae668d357ae 100644 (file)
@@ -33,6 +33,7 @@ Object::Object()
        name = "";
        mesh = NULL;
        tfm = transform_identity();
+       visibility = ~0;
 }
 
 Object::~Object()
index 7a12a06853b76a64261cffaab269e807cbff9294..7fe83cf7d914f1afcc67f1adc108bbd83f7a8c3d 100644 (file)
@@ -42,6 +42,7 @@ public:
        BoundBox bounds;
        ustring name;
        vector<ParamValue> attributes;
+       uint visibility;
 
        Object();
        ~Object();
index 9d475cd9fa534f9b73e03cd7a1e28b7b4c8dc034..5772a9d726856e5b27a83cd291a5cb23df26172b 100644 (file)
@@ -57,6 +57,7 @@ public:
        device_vector<float4> bvh_nodes;
        device_vector<uint> object_node;
        device_vector<float4> tri_woop;
+       device_vector<uint> prim_visibility;
        device_vector<uint> prim_index;
        device_vector<uint> prim_object;
 
index 0b7915476287644697a3f2128e542dfed5e68a4a..504068722d7435acbde52fd7ecdbc69e863f4f51 100644 (file)
@@ -1,6 +1,11 @@
 import bpy
 cycles = bpy.context.scene.cycles
 
-cycles.max_bounces = 0
-cycles.min_bounces = 0
-cycles.no_caustics = False
+cycles.max_bounces = 8
+cycles.min_bounces = 8
+cycles.no_caustics = True
+cycles.diffuse_bounces = 0
+cycles.glossy_bounces = 1
+cycles.transmission_bounces = 2
+cycles.transparent_min_bounces = 8
+cycles.transparent_max_bounces = 8
diff --git a/release/scripts/presets/cycles/integrator/full_global_illumination.py b/release/scripts/presets/cycles/integrator/full_global_illumination.py
new file mode 100644 (file)
index 0000000..47c4431
--- /dev/null
@@ -0,0 +1,11 @@
+import bpy
+cycles = bpy.context.scene.cycles
+
+cycles.max_bounces = 1024
+cycles.min_bounces = 3
+cycles.no_caustics = False
+cycles.diffuse_bounces = 1024
+cycles.glossy_bounces = 1024
+cycles.transmission_bounces = 1024
+cycles.transparent_min_bounces = 8
+cycles.transparent_max_bounces = 1024
diff --git a/release/scripts/presets/cycles/integrator/limited_global_illumination.py b/release/scripts/presets/cycles/integrator/limited_global_illumination.py
new file mode 100644 (file)
index 0000000..f2a7e1f
--- /dev/null
@@ -0,0 +1,11 @@
+import bpy
+cycles = bpy.context.scene.cycles
+
+cycles.max_bounces = 8
+cycles.min_bounces = 3
+cycles.no_caustics = True
+cycles.diffuse_bounces = 1
+cycles.glossy_bounces = 4
+cycles.transmission_bounces = 8
+cycles.transparent_min_bounces = 8
+cycles.transparent_max_bounces = 8
index 262bf3ff11503b073b402e29874ae52f0a89b389..7f42c70b338135286b444519b3b17c676febe08a 100644 (file)
@@ -33,7 +33,7 @@
 
 static bNodeSocketType sh_node_bsdf_glass_in[]= {
        {       SOCK_RGBA, 1, "Color",          0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
-       {       SOCK_VALUE, 1, "Roughness",     0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Roughness",     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 1, "Fresnel",       0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
index 3bf32f42370a1b3b5d76f9c3f3496ce558a149ab..f828f66c3e63877d445b89b4e185a3b0d9088116 100644 (file)
@@ -36,6 +36,7 @@ static bNodeSocketType sh_node_light_path_out[]= {
        {       SOCK_VALUE, 0, "Is Shadow Ray",                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 0, "Is Diffuse Ray",                0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 0, "Is Glossy Ray",                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "Is Singular Ray",               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 0, "Is Reflection Ray",             0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 0, "Is Transmission Ray",   0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }