Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2011-09-01 19:53:36 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2011-09-01 19:53:36 +0400
commitdf625253ac0dec5be70701e2694c1e0358343fbf (patch)
tree10b216af9eb607023a3b280b8641acf336e34b10 /intern/cycles
parent1e741b3a52cc44b7a3ee173f180fd3d99c958efc (diff)
Cycles:
* 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
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/app/cycles_xml.cpp4
-rw-r--r--intern/cycles/blender/addon/presets.py5
-rw-r--r--intern/cycles/blender/addon/properties.py58
-rw-r--r--intern/cycles/blender/addon/ui.py56
-rw-r--r--intern/cycles/blender/blender_object.cpp19
-rw-r--r--intern/cycles/blender/blender_shader.cpp2
-rw-r--r--intern/cycles/blender/blender_sync.cpp14
-rw-r--r--intern/cycles/bvh/bvh.cpp43
-rw-r--r--intern/cycles/bvh/bvh.h6
-rw-r--r--intern/cycles/bvh/bvh_build.cpp9
-rw-r--r--intern/cycles/bvh/bvh_node.h5
-rw-r--r--intern/cycles/kernel/kernel.cpp4
-rw-r--r--intern/cycles/kernel/kernel_bvh.h38
-rw-r--r--intern/cycles/kernel/kernel_path.h172
-rw-r--r--intern/cycles/kernel/kernel_textures.h1
-rw-r--r--intern/cycles/kernel/kernel_types.h23
-rw-r--r--intern/cycles/kernel/osl/nodes/node_light_path.osl2
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp4
-rw-r--r--intern/cycles/kernel/svm/bsdf_transparent.h2
-rw-r--r--intern/cycles/kernel/svm/svm_light_path.h1
-rw-r--r--intern/cycles/kernel/svm/svm_noise.h17
-rw-r--r--intern/cycles/kernel/svm/svm_texture.h4
-rw-r--r--intern/cycles/kernel/svm/svm_types.h1
-rw-r--r--intern/cycles/render/integrator.cpp49
-rw-r--r--intern/cycles/render/integrator.h15
-rw-r--r--intern/cycles/render/mesh.cpp6
-rw-r--r--intern/cycles/render/nodes.cpp11
-rw-r--r--intern/cycles/render/object.cpp1
-rw-r--r--intern/cycles/render/object.h1
-rw-r--r--intern/cycles/render/scene.h1
30 files changed, 425 insertions, 149 deletions
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 0e80cd80ece..7c3fb0b3625 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -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");
}
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 983d6dd471c..e5243b633be 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -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"
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index b2d982fdabc..ca38520d28f 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -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)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index dc102b97db8..001aacea3eb 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -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
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 52081cc0b60..f1ba2dba2f5 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -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;
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 9024de092b7..4e19ee82f77 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -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);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index c579253336f..40ec4838dad 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -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);
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 664bdd98b1f..9bd748157bf 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -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)
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 79e46d6a13c..e502af72335 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -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
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 3e47cb75014..d3e84e11d53 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -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;
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index f8f0ffecd95..5e0a17a1193 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -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;
}
diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp
index d9ba237d964..01682d11f33 100644
--- a/intern/cycles/kernel/kernel.cpp
+++ b/intern/cycles/kernel/kernel.cpp
@@ -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;
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index 4dea540e31c..df7663b5555 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -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++;
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index d4ed4651751..7f7aaad3270 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -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);
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index dd4566ec184..19635b2664c 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -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)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 06581d593e4..5881f090944 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -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;
diff --git a/intern/cycles/kernel/osl/nodes/node_light_path.osl b/intern/cycles/kernel/osl/nodes/node_light_path.osl
index 081640428ab..0ead20bf2bb 100644
--- a/intern/cycles/kernel/osl/nodes/node_light_path.osl
+++ b/intern/cycles/kernel/osl/nodes/node_light_path.osl
@@ -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");
}
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 007d14b526b..73ff4f41423 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -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;
diff --git a/intern/cycles/kernel/svm/bsdf_transparent.h b/intern/cycles/kernel/svm/bsdf_transparent.h
index 30288bf251d..1674f04955e 100644
--- a/intern/cycles/kernel/svm/bsdf_transparent.h
+++ b/intern/cycles/kernel/svm/bsdf_transparent.h
@@ -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
diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h
index d6413d1569e..1b13fd93a0f 100644
--- a/intern/cycles/kernel/svm/svm_light_path.h
+++ b/intern/cycles/kernel/svm/svm_light_path.h
@@ -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;
diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h
index 72ff353abb4..28ad028ad0e 100644
--- a/intern/cycles/kernel/svm/svm_noise.h
+++ b/intern/cycles/kernel/svm/svm_noise.h
@@ -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
diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h
index 0bf0cf8c2cd..e273a92c988 100644
--- a/intern/cycles/kernel/svm/svm_texture.h
+++ b/intern/cycles/kernel/svm/svm_texture.h
@@ -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;
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 786478c0c03..758ba25c07a 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -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
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 30736670cc3..57689be3965 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -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);
}
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index b7d0c48131f..5bab4470089 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -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;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index b9163309652..b73013fc378 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -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();
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 5ffc3fbbabb..900115d2231 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -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);
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 06c93e48b89..4ba2de6e61b 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -33,6 +33,7 @@ Object::Object()
name = "";
mesh = NULL;
tfm = transform_identity();
+ visibility = ~0;
}
Object::~Object()
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 7a12a06853b..7fe83cf7d91 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -42,6 +42,7 @@ public:
BoundBox bounds;
ustring name;
vector<ParamValue> attributes;
+ uint visibility;
Object();
~Object();
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 9d475cd9fa5..5772a9d7268 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -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;