diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-01 19:53:36 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-01 19:53:36 +0400 |
commit | df625253ac0dec5be70701e2694c1e0358343fbf (patch) | |
tree | 10b216af9eb607023a3b280b8641acf336e34b10 | |
parent | 1e741b3a52cc44b7a3ee173f180fd3d99c958efc (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
35 files changed, 457 insertions, 153 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; diff --git a/release/scripts/presets/cycles/integrator/direct_light.py b/release/scripts/presets/cycles/integrator/direct_light.py index 0b791547628..504068722d7 100644 --- a/release/scripts/presets/cycles/integrator/direct_light.py +++ b/release/scripts/presets/cycles/integrator/direct_light.py @@ -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 index 00000000000..47c4431de13 --- /dev/null +++ b/release/scripts/presets/cycles/integrator/full_global_illumination.py @@ -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 index 00000000000..f2a7e1f7b7a --- /dev/null +++ b/release/scripts/presets/cycles/integrator/limited_global_illumination.py @@ -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 diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_bsdf_glass.c b/source/blender/nodes/intern/SHD_nodes/SHD_bsdf_glass.c index 262bf3ff115..7f42c70b338 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_bsdf_glass.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_bsdf_glass.c @@ -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, "" } }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_light_path.c b/source/blender/nodes/intern/SHD_nodes/SHD_light_path.c index 3bf32f42370..f828f66c3e6 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_light_path.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_light_path.c @@ -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, "" } |