forked from bartvdbraak/blender
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
This commit is contained in:
parent
1e741b3a52
commit
df625253ac
@ -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");
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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.prop(cscene, "max_bounces")
|
||||
sub.prop(cscene, "min_bounces")
|
||||
sub.label(text="Bounces:")
|
||||
sub.prop(cscene, "max_bounces", text="Max")
|
||||
sub.prop(cscene, "min_bounces", text="Min")
|
||||
|
||||
sub = col.column(align=True)
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
|
||||
path_flag |= PATH_RAY_SINGULAR;
|
||||
path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
|
||||
state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR;
|
||||
state->flag &= ~PATH_RAY_DIFFUSE;
|
||||
}
|
||||
|
||||
/* ray through transparent is still camera ray */
|
||||
if(!(label & LABEL_STRAIGHT))
|
||||
path_flag &= ~PATH_RAY_CAMERA;
|
||||
|
||||
return path_flag;
|
||||
}
|
||||
|
||||
__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);
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -33,6 +33,7 @@ Object::Object()
|
||||
name = "";
|
||||
mesh = NULL;
|
||||
tfm = transform_identity();
|
||||
visibility = ~0;
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
BoundBox bounds;
|
||||
ustring name;
|
||||
vector<ParamValue> attributes;
|
||||
uint visibility;
|
||||
|
||||
Object();
|
||||
~Object();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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, "" }
|
||||
};
|
||||
|
@ -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, "" }
|
||||
|
Loading…
Reference in New Issue
Block a user