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;
|
Integrator *integrator = state.scene->integrator;
|
||||||
|
|
||||||
xml_read_int(&integrator->minbounce, node, "min_bounce");
|
xml_read_int(&integrator->min_bounce, node, "min_bounce");
|
||||||
xml_read_int(&integrator->maxbounce, node, "max_bounce");
|
xml_read_int(&integrator->max_bounce, node, "max_bounce");
|
||||||
xml_read_bool(&integrator->no_caustics, node, "no_caustics");
|
xml_read_bool(&integrator->no_caustics, node, "no_caustics");
|
||||||
xml_read_float(&integrator->blur_caustics, node, "blur_caustics");
|
xml_read_float(&integrator->blur_caustics, node, "blur_caustics");
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,11 @@ class AddPresetIntegrator(AddPresetBase, Operator):
|
|||||||
"cycles.max_bounces",
|
"cycles.max_bounces",
|
||||||
"cycles.min_bounces",
|
"cycles.min_bounces",
|
||||||
"cycles.no_caustics",
|
"cycles.no_caustics",
|
||||||
|
"cycles.diffuse_bounces",
|
||||||
|
"cycles.glossy_bounces",
|
||||||
|
"cycles.transmission_bounces",
|
||||||
|
"cycles.transparent_min_bounces",
|
||||||
|
"cycles.transparent_max_bounces"
|
||||||
]
|
]
|
||||||
|
|
||||||
preset_subdir = "cycles/integrator"
|
preset_subdir = "cycles/integrator"
|
||||||
|
@ -24,7 +24,7 @@ from cycles import enums
|
|||||||
class CyclesRenderSettings(bpy.types.PropertyGroup):
|
class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
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",
|
cls.device = EnumProperty(name="Device", description="Device to use for rendering",
|
||||||
items=enums.devices, default="CPU")
|
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",
|
cls.preview_pause = BoolProperty(name="Pause Preview", description="Pause all viewport preview renders",
|
||||||
default=False)
|
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",
|
cls.no_caustics = BoolProperty(name="No Caustics", description="Leave out caustics, resulting in a darker image with less noise",
|
||||||
default=False)
|
default=False)
|
||||||
cls.blur_caustics = FloatProperty(name="Blur Caustics", description="Blur caustics to reduce noise",
|
cls.blur_caustics = FloatProperty(name="Blur Caustics", description="Blur caustics to reduce noise",
|
||||||
default=0.0, min=0.0, max=1.0)
|
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)
|
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)
|
default=False)
|
||||||
|
|
||||||
cls.filter_type = EnumProperty(name="Filter Type", description="Pixel filter type",
|
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):
|
class CyclesCameraSettings(bpy.types.PropertyGroup):
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
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",
|
cls.lens_radius = FloatProperty(name="Lens radius", description="Lens radius for depth of field",
|
||||||
default=0.0, min=0.0, max=10.0)
|
default=0.0, min=0.0, max=10.0)
|
||||||
@ -93,7 +106,7 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
|
|||||||
class CyclesMaterialSettings(bpy.types.PropertyGroup):
|
class CyclesMaterialSettings(bpy.types.PropertyGroup):
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
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
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
@ -102,18 +115,33 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
|
|||||||
class CyclesWorldSettings(bpy.types.PropertyGroup):
|
class CyclesWorldSettings(bpy.types.PropertyGroup):
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
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
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
del bpy.types.World.cycles
|
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):
|
class CyclesMeshSettings(bpy.types.PropertyGroup):
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.Mesh.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.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.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",
|
cls.displacement_method = EnumProperty(name="Displacement Method", description="Method to use for the displacement",
|
||||||
items=enums.displacement_methods, default="BUMP")
|
items=enums.displacement_methods, default="BUMP")
|
||||||
@ -124,12 +152,15 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
del bpy.types.Mesh.cycles
|
del bpy.types.Mesh.cycles
|
||||||
|
del bpy.types.Curve.cycles
|
||||||
|
del bpy.types.MetaBall.cycles
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
bpy.utils.register_class(CyclesRenderSettings)
|
bpy.utils.register_class(CyclesRenderSettings)
|
||||||
bpy.utils.register_class(CyclesCameraSettings)
|
bpy.utils.register_class(CyclesCameraSettings)
|
||||||
bpy.utils.register_class(CyclesMaterialSettings)
|
bpy.utils.register_class(CyclesMaterialSettings)
|
||||||
bpy.utils.register_class(CyclesWorldSettings)
|
bpy.utils.register_class(CyclesWorldSettings)
|
||||||
|
bpy.utils.register_class(CyclesVisibilitySettings)
|
||||||
bpy.utils.register_class(CyclesMeshSettings)
|
bpy.utils.register_class(CyclesMeshSettings)
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
@ -138,4 +169,5 @@ def unregister():
|
|||||||
bpy.utils.unregister_class(CyclesMaterialSettings)
|
bpy.utils.unregister_class(CyclesMaterialSettings)
|
||||||
bpy.utils.unregister_class(CyclesWorldSettings)
|
bpy.utils.unregister_class(CyclesWorldSettings)
|
||||||
bpy.utils.unregister_class(CyclesMeshSettings)
|
bpy.utils.unregister_class(CyclesMeshSettings)
|
||||||
|
bpy.utils.unregister_class(CyclesVisibilitySettings)
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ class CyclesButtonsPanel():
|
|||||||
|
|
||||||
class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
|
class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
|
||||||
bl_label = "Integrator"
|
bl_label = "Integrator"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
@ -58,14 +59,28 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
|
|||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
sub.prop(cscene, "passes", text="Render Passes")
|
sub.label(text="Passes:")
|
||||||
sub.prop(cscene, "preview_passes")
|
sub.prop(cscene, "passes", text="Render")
|
||||||
col.prop(cscene, "no_caustics")
|
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()
|
col = split.column()
|
||||||
|
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
sub.prop(cscene, "max_bounces")
|
sub.label(text="Bounces:")
|
||||||
sub.prop(cscene, "min_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 = col.row()
|
||||||
#row.prop(cscene, "blur_caustics")
|
#row.prop(cscene, "blur_caustics")
|
||||||
@ -83,8 +98,8 @@ class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
|
|||||||
split = layout.split()
|
split = layout.split()
|
||||||
|
|
||||||
col = split.column();
|
col = split.column();
|
||||||
col.prop(cscene, "exposure")
|
col.prop(cscene, "film_exposure")
|
||||||
col.prop(cscene, "transparent")
|
col.prop(cscene, "film_transparent")
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
@ -233,6 +248,33 @@ class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
|
|||||||
layout.prop(cdata, "use_subdivision");
|
layout.prop(cdata, "use_subdivision");
|
||||||
layout.prop(cdata, "dicing_rate");
|
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):
|
def find_node(material, nodetype):
|
||||||
if material and material.node_tree:
|
if material and material.node_tree:
|
||||||
ntree = 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));
|
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 */
|
/* Light */
|
||||||
|
|
||||||
void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
|
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)) {
|
if(object_map.sync(&object, b_ob, b_parent, key)) {
|
||||||
object->name = b_ob.name();
|
object->name = b_ob.name();
|
||||||
object->tfm = tfm;
|
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->tag_update(scene);
|
||||||
object_updated = true;
|
object_updated = true;
|
||||||
}
|
}
|
||||||
|
@ -599,7 +599,7 @@ void BlenderSync::sync_world()
|
|||||||
}
|
}
|
||||||
|
|
||||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
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))
|
if(background->modified(prevbackground))
|
||||||
background->tag_update(scene);
|
background->tag_update(scene);
|
||||||
|
@ -131,8 +131,16 @@ void BlenderSync::sync_integrator()
|
|||||||
Integrator *integrator = scene->integrator;
|
Integrator *integrator = scene->integrator;
|
||||||
Integrator previntegrator = *integrator;
|
Integrator previntegrator = *integrator;
|
||||||
|
|
||||||
integrator->minbounce = get_int(cscene, "min_bounces");
|
integrator->min_bounce = get_int(cscene, "min_bounces");
|
||||||
integrator->maxbounce = get_int(cscene, "max_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->no_caustics = get_boolean(cscene, "no_caustics");
|
||||||
integrator->blur_caustics = get_float(cscene, "blur_caustics");
|
integrator->blur_caustics = get_float(cscene, "blur_caustics");
|
||||||
|
|
||||||
@ -149,7 +157,7 @@ void BlenderSync::sync_film()
|
|||||||
Film *film = scene->film;
|
Film *film = scene->film;
|
||||||
Film prevfilm = *film;
|
Film prevfilm = *film;
|
||||||
|
|
||||||
film->exposure = get_float(cscene, "exposure");
|
film->exposure = get_float(cscene, "film_exposure");
|
||||||
|
|
||||||
if(film->modified(prevfilm))
|
if(film->modified(prevfilm))
|
||||||
film->tag_update(scene);
|
film->tag_update(scene);
|
||||||
|
@ -84,6 +84,7 @@ bool BVH::cache_read(CacheData& key)
|
|||||||
value.read(pack.nodes);
|
value.read(pack.nodes);
|
||||||
value.read(pack.object_node);
|
value.read(pack.object_node);
|
||||||
value.read(pack.tri_woop);
|
value.read(pack.tri_woop);
|
||||||
|
value.read(pack.prim_visibility);
|
||||||
value.read(pack.prim_index);
|
value.read(pack.prim_index);
|
||||||
value.read(pack.prim_object);
|
value.read(pack.prim_object);
|
||||||
value.read(pack.is_leaf);
|
value.read(pack.is_leaf);
|
||||||
@ -103,6 +104,7 @@ void BVH::cache_write(CacheData& key)
|
|||||||
value.add(pack.nodes);
|
value.add(pack.nodes);
|
||||||
value.add(pack.object_node);
|
value.add(pack.object_node);
|
||||||
value.add(pack.tri_woop);
|
value.add(pack.tri_woop);
|
||||||
|
value.add(pack.prim_visibility);
|
||||||
value.add(pack.prim_index);
|
value.add(pack.prim_index);
|
||||||
value.add(pack.prim_object);
|
value.add(pack.prim_object);
|
||||||
value.add(pack.is_leaf);
|
value.add(pack.is_leaf);
|
||||||
@ -236,6 +238,8 @@ void BVH::pack_triangles()
|
|||||||
|
|
||||||
pack.tri_woop.clear();
|
pack.tri_woop.clear();
|
||||||
pack.tri_woop.resize(tidx_size * nsize);
|
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++) {
|
for(unsigned int i = 0; i < tidx_size; i++) {
|
||||||
if(pack.prim_index[i] != -1) {
|
if(pack.prim_index[i] != -1) {
|
||||||
@ -243,6 +247,10 @@ void BVH::pack_triangles()
|
|||||||
|
|
||||||
pack_triangle(i, woop);
|
pack_triangle(i, woop);
|
||||||
memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
|
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_index.resize(prim_index_size);
|
||||||
pack.prim_object.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.tri_woop.resize(tri_woop_size);
|
||||||
pack.nodes.resize(nodes_size);
|
pack.nodes.resize(nodes_size);
|
||||||
pack.object_node.resize(objects.size());
|
pack.object_node.resize(objects.size());
|
||||||
|
|
||||||
int *pack_prim_index = &pack.prim_index[0];
|
int *pack_prim_index = &pack.prim_index[0];
|
||||||
int *pack_prim_object = &pack.prim_object[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];
|
float4 *pack_tri_woop = &pack.tri_woop[0];
|
||||||
int4 *pack_nodes = &pack.nodes[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();
|
size_t bvh_prim_index_size = bvh->pack.prim_index.size();
|
||||||
int *bvh_prim_index = &bvh->pack.prim_index[0];
|
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++) {
|
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_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_object[pack_prim_index_offset] = 0; // unused for instances
|
||||||
pack_prim_index_offset++;
|
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)
|
if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1)
|
||||||
/* object */
|
/* 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
|
else
|
||||||
/* triangle */
|
/* 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)
|
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] =
|
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(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(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(__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);
|
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);
|
assert(!params.top_level);
|
||||||
|
|
||||||
BoundBox bbox;
|
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];
|
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[1]]);
|
||||||
bbox.grow(vpos[vidx[2]]);
|
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 {
|
else {
|
||||||
/* refit inner node, set bbox from children */
|
/* refit inner node, set bbox from children */
|
||||||
BoundBox bbox0, bbox1;
|
BoundBox bbox0, bbox1;
|
||||||
|
uint visibility0 = 0, visibility1 = 0;
|
||||||
|
|
||||||
refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0);
|
refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0);
|
||||||
refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1);
|
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(bbox0);
|
||||||
bbox.grow(bbox1);
|
bbox.grow(bbox1);
|
||||||
|
visibility = visibility0|visibility1;
|
||||||
pack_node(idx, bbox0, bbox1, c0, c1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,6 +540,8 @@ QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_)
|
|||||||
: BVH(params_, objects_)
|
: BVH(params_, objects_)
|
||||||
{
|
{
|
||||||
params.use_qbvh = true;
|
params.use_qbvh = true;
|
||||||
|
|
||||||
|
/* todo: use visibility */
|
||||||
}
|
}
|
||||||
|
|
||||||
void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
|
void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
|
||||||
|
@ -51,6 +51,8 @@ struct PackedBVH {
|
|||||||
array<int> object_node;
|
array<int> object_node;
|
||||||
/* precomputed triangle intersection data, one triangle is 4x float4 */
|
/* precomputed triangle intersection data, one triangle is 4x float4 */
|
||||||
array<float4> tri_woop;
|
array<float4> tri_woop;
|
||||||
|
/* visibility visibilitys for primitives */
|
||||||
|
array<uint> prim_visibility;
|
||||||
/* mapping from BVH primitive index to true primitive index, as primitives
|
/* mapping from BVH primitive index to true primitive index, as primitives
|
||||||
may be duplicated due to spatial splits. -1 for instances. */
|
may be duplicated due to spatial splits. -1 for instances. */
|
||||||
array<int> prim_index;
|
array<int> prim_index;
|
||||||
@ -121,11 +123,11 @@ protected:
|
|||||||
void pack_nodes(const array<int>& prims, const BVHNode *root);
|
void pack_nodes(const array<int>& prims, const BVHNode *root);
|
||||||
void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
|
void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
|
||||||
void pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1);
|
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 */
|
/* refit */
|
||||||
void refit_nodes();
|
void refit_nodes();
|
||||||
void refit_node(int idx, bool leaf, BoundBox& bbox);
|
void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* QBVH
|
/* QBVH
|
||||||
|
@ -218,12 +218,13 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const Reference *ref, int num)
|
|||||||
{
|
{
|
||||||
if(num == 0) {
|
if(num == 0) {
|
||||||
BoundBox bounds;
|
BoundBox bounds;
|
||||||
return new LeafNode(bounds, 0, 0);
|
return new LeafNode(bounds, 0, 0, 0);
|
||||||
}
|
}
|
||||||
else if(num == 1) {
|
else if(num == 1) {
|
||||||
prim_index.push_back(ref[0].prim_index);
|
prim_index.push_back(ref[0].prim_index);
|
||||||
prim_object.push_back(ref[0].prim_object);
|
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 {
|
else {
|
||||||
int mid = num/2;
|
int mid = num/2;
|
||||||
@ -244,12 +245,14 @@ BVHNode* BVHBuild::create_leaf_node(const NodeSpec& spec)
|
|||||||
vector<int>& p_object = prim_object;
|
vector<int>& p_object = prim_object;
|
||||||
BoundBox bounds;
|
BoundBox bounds;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
uint visibility = 0;
|
||||||
|
|
||||||
for(int i = 0; i < spec.num; i++) {
|
for(int i = 0; i < spec.num; i++) {
|
||||||
if(references.back().prim_index != -1) {
|
if(references.back().prim_index != -1) {
|
||||||
p_index.push_back(references.back().prim_index);
|
p_index.push_back(references.back().prim_index);
|
||||||
p_object.push_back(references.back().prim_object);
|
p_object.push_back(references.back().prim_object);
|
||||||
bounds.grow(references.back().bounds);
|
bounds.grow(references.back().bounds);
|
||||||
|
visibility |= objects[references.back().prim_object]->visibility;
|
||||||
references.pop_back();
|
references.pop_back();
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
@ -258,7 +261,7 @@ BVHNode* BVHBuild::create_leaf_node(const NodeSpec& spec)
|
|||||||
BVHNode *leaf = NULL;
|
BVHNode *leaf = NULL;
|
||||||
|
|
||||||
if(num > 0) {
|
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)
|
if(num == spec.num)
|
||||||
return leaf;
|
return leaf;
|
||||||
|
@ -52,6 +52,7 @@ public:
|
|||||||
float getArea() const { return m_bounds.area(); }
|
float getArea() const { return m_bounds.area(); }
|
||||||
|
|
||||||
BoundBox m_bounds;
|
BoundBox m_bounds;
|
||||||
|
uint m_visibility;
|
||||||
|
|
||||||
// Subtree functions
|
// Subtree functions
|
||||||
int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const;
|
int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const;
|
||||||
@ -65,6 +66,7 @@ public:
|
|||||||
InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1)
|
InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1)
|
||||||
{
|
{
|
||||||
m_bounds = bounds;
|
m_bounds = bounds;
|
||||||
|
m_visibility = child0->m_visibility|child1->m_visibility;
|
||||||
children[0] = child0;
|
children[0] = child0;
|
||||||
children[1] = child1;
|
children[1] = child1;
|
||||||
}
|
}
|
||||||
@ -80,9 +82,10 @@ public:
|
|||||||
class LeafNode : public BVHNode
|
class LeafNode : public BVHNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LeafNode(const BoundBox& bounds, int lo, int hi)
|
LeafNode(const BoundBox& bounds, uint visibility, int lo, int hi)
|
||||||
{
|
{
|
||||||
m_bounds = bounds;
|
m_bounds = bounds;
|
||||||
|
m_visibility = visibility;
|
||||||
m_lo = lo;
|
m_lo = lo;
|
||||||
m_hi = hi;
|
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.data = (float4*)mem;
|
||||||
kg->__tri_woop.width = width;
|
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) {
|
else if(strcmp(name, "__prim_index") == 0) {
|
||||||
kg->__prim_index.data = (uint*)mem;
|
kg->__prim_index.data = (uint*)mem;
|
||||||
kg->__prim_index.width = width;
|
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,
|
__device_inline void bvh_node_intersect(KernelGlobals *kg,
|
||||||
bool *traverseChild0, bool *traverseChild1,
|
bool *traverseChild0, bool *traverseChild1,
|
||||||
bool *closestChild1, int *nodeAddr0, int *nodeAddr1,
|
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 */
|
/* fetch node data */
|
||||||
float4 n0xy = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
|
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);
|
float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
|
||||||
|
|
||||||
/* decide which nodes to traverse next */
|
/* 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);
|
*traverseChild0 = (c0max >= c0min);
|
||||||
*traverseChild1 = (c1max >= c1min);
|
*traverseChild1 = (c1max >= c1min);
|
||||||
|
#endif
|
||||||
|
|
||||||
*nodeAddr0 = __float_as_int(cnodes.x);
|
*nodeAddr0 = __float_as_int(cnodes.x);
|
||||||
*nodeAddr1 = __float_as_int(cnodes.y);
|
*nodeAddr1 = __float_as_int(cnodes.y);
|
||||||
@ -121,7 +127,8 @@ __device_inline void bvh_node_intersect(KernelGlobals *kg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sven Woop's algorithm */
|
/* 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 */
|
/* compute and check intersection t-value */
|
||||||
float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
|
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;
|
float v = Oy + t*Dy;
|
||||||
|
|
||||||
if(v >= 0.0f && u + v <= 1.0f) {
|
if(v >= 0.0f && u + v <= 1.0f) {
|
||||||
/* record intersection */
|
#ifdef __VISIBILITY_FLAG__
|
||||||
isect->prim = triAddr;
|
/* visibility flag test. we do it here under the assumption
|
||||||
isect->object = object;
|
that most triangles are culled by node flags */
|
||||||
isect->u = u;
|
if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
|
||||||
isect->v = v;
|
#endif
|
||||||
isect->t = t;
|
{
|
||||||
|
/* 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 */
|
/* traversal stack in CUDA thread-local memory */
|
||||||
int traversalStack[BVH_STACK_SIZE];
|
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,
|
bvh_node_intersect(kg, &traverseChild0, &traverseChild1,
|
||||||
&closestChild1, &nodeAddr, &nodeAddrChild1,
|
&closestChild1, &nodeAddr, &nodeAddrChild1,
|
||||||
P, idir, isect->t, nodeAddr);
|
P, idir, isect->t, visibility, nodeAddr);
|
||||||
|
|
||||||
if(traverseChild0 != traverseChild1) {
|
if(traverseChild0 != traverseChild1) {
|
||||||
/* one child was intersected */
|
/* one child was intersected */
|
||||||
@ -236,10 +250,10 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const bo
|
|||||||
/* triangle intersection */
|
/* triangle intersection */
|
||||||
while(primAddr < primAddr2) {
|
while(primAddr < primAddr2) {
|
||||||
/* intersect ray against triangle */
|
/* 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 */
|
/* shadow ray early termination */
|
||||||
if(isshadowray && isect->prim != ~0)
|
if(visibility == PATH_RAY_SHADOW && isect->prim != ~0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
primAddr++;
|
primAddr++;
|
||||||
|
@ -58,51 +58,108 @@ __device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global f
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__device float path_terminate_probability(KernelGlobals *kg, int bounce, const float3 throughput)
|
typedef struct PathState {
|
||||||
{
|
uint flag;
|
||||||
if(bounce >= kernel_data.integrator.maxbounce)
|
int bounce;
|
||||||
return 0.0f;
|
|
||||||
else if(bounce <= kernel_data.integrator.minbounce)
|
|
||||||
return 1.0f;
|
|
||||||
|
|
||||||
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) {
|
if(label & LABEL_REFLECT) {
|
||||||
path_flag |= PATH_RAY_REFLECT;
|
state->flag |= PATH_RAY_REFLECT;
|
||||||
path_flag &= ~PATH_RAY_TRANSMIT;
|
state->flag &= ~(PATH_RAY_TRANSMIT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
|
||||||
|
|
||||||
|
if(label & LABEL_DIFFUSE)
|
||||||
|
state->diffuse_bounce++;
|
||||||
|
else
|
||||||
|
state->glossy_bounce++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
kernel_assert(label & LABEL_TRANSMIT);
|
kernel_assert(label & LABEL_TRANSMIT);
|
||||||
|
|
||||||
path_flag |= PATH_RAY_TRANSMIT;
|
state->flag |= PATH_RAY_TRANSMIT;
|
||||||
path_flag &= ~PATH_RAY_REFLECT;
|
state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
|
||||||
|
|
||||||
|
state->transmission_bounce++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* diffuse/glossy/singular */
|
/* diffuse/glossy/singular */
|
||||||
if(label & LABEL_DIFFUSE) {
|
if(label & LABEL_DIFFUSE) {
|
||||||
path_flag |= PATH_RAY_DIFFUSE;
|
state->flag |= PATH_RAY_DIFFUSE;
|
||||||
path_flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR);
|
state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR);
|
||||||
}
|
}
|
||||||
else if(label & LABEL_GLOSSY) {
|
else if(label & LABEL_GLOSSY) {
|
||||||
path_flag |= PATH_RAY_GLOSSY;
|
state->flag |= PATH_RAY_GLOSSY;
|
||||||
path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR);
|
state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
kernel_assert(label & (LABEL_SINGULAR|LABEL_STRAIGHT));
|
kernel_assert(label & LABEL_SINGULAR);
|
||||||
|
|
||||||
path_flag |= PATH_RAY_SINGULAR;
|
state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR;
|
||||||
path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
|
state->flag &= ~PATH_RAY_DIFFUSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* ray through transparent is still camera ray */
|
|
||||||
if(!(label & LABEL_STRAIGHT))
|
__device_inline uint path_state_ray_visibility(PathState *state)
|
||||||
path_flag &= ~PATH_RAY_CAMERA;
|
{
|
||||||
|
uint flag = state->flag;
|
||||||
return path_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)
|
__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__
|
#ifdef __EMISSION__
|
||||||
float ray_pdf = 0.0f;
|
float ray_pdf = 0.0f;
|
||||||
#endif
|
#endif
|
||||||
int path_flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR;
|
PathState state;
|
||||||
int rng_offset = PRNG_BASE_NUM;
|
int rng_offset = PRNG_BASE_NUM;
|
||||||
|
|
||||||
|
path_state_init(&state);
|
||||||
|
|
||||||
/* path iteration */
|
/* path iteration */
|
||||||
for(int bounce = 0; ; bounce++, rng_offset += PRNG_BOUNCE_NUM) {
|
for(;; rng_offset += PRNG_BOUNCE_NUM) {
|
||||||
/* intersect scene */
|
/* intersect scene */
|
||||||
Intersection isect;
|
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 */
|
/* 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);
|
Ltransparent += average(throughput);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef __BACKGROUND__
|
#ifdef __BACKGROUND__
|
||||||
ShaderData sd;
|
ShaderData sd;
|
||||||
shader_setup_from_background(kg, &sd, &ray);
|
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);
|
shader_release(kg, &sd);
|
||||||
#else
|
#else
|
||||||
L += make_float3(0.8f, 0.8f, 0.8f);
|
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;
|
ShaderData sd;
|
||||||
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
||||||
float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF);
|
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__
|
#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);
|
float3 holdout_weight = shader_holdout_eval(kg, &sd);
|
||||||
|
|
||||||
if(kernel_data.background.transparent)
|
if(kernel_data.background.transparent)
|
||||||
@ -160,11 +220,25 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
|
|||||||
/* emission */
|
/* emission */
|
||||||
if(kernel_data.integrator.use_emission) {
|
if(kernel_data.integrator.use_emission) {
|
||||||
if(sd.flag & SD_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 */
|
/* sample illumination from lights to find path contribution */
|
||||||
if((sd.flag & SD_BSDF_HAS_EVAL) &&
|
if(sd.flag & SD_BSDF_HAS_EVAL) {
|
||||||
bounce != kernel_data.integrator.maxbounce) {
|
|
||||||
float light_t = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT);
|
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_o = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_F);
|
||||||
float light_u = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_U);
|
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;
|
Ray light_ray;
|
||||||
float3 light_L;
|
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)) {
|
if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
|
||||||
/* trace shadow ray */
|
/* 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;
|
L += throughput*light_L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,10 +259,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* no BSDF? we can stop here */
|
/* no BSDF? we can stop here */
|
||||||
if(!(sd.flag & SD_BSDF)) {
|
if(!(sd.flag & SD_BSDF))
|
||||||
path_flag &= ~PATH_RAY_CAMERA;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* sample BSDF */
|
/* sample BSDF */
|
||||||
float bsdf_pdf;
|
float bsdf_pdf;
|
||||||
@ -202,10 +276,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
|
|||||||
|
|
||||||
shader_release(kg, &sd);
|
shader_release(kg, &sd);
|
||||||
|
|
||||||
if(bsdf_pdf == 0.0f || is_zero(bsdf_eval)) {
|
if(bsdf_pdf == 0.0f || is_zero(bsdf_eval))
|
||||||
path_flag &= ~PATH_RAY_CAMERA;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* modify throughput */
|
/* modify throughput */
|
||||||
throughput *= bsdf_eval/bsdf_pdf;
|
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;
|
ray_pdf = bsdf_pdf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
path_flag = path_flag_from_label(path_flag, label);
|
/* update path state */
|
||||||
|
path_state_next(&state, 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;
|
|
||||||
|
|
||||||
/* setup ray */
|
/* setup ray */
|
||||||
ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
|
ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
/* bvh */
|
/* bvh */
|
||||||
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
|
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
|
||||||
KERNEL_TEX(float4, texture_float4, __tri_woop)
|
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_index)
|
||||||
KERNEL_TEX(uint, texture_uint, __prim_object)
|
KERNEL_TEX(uint, texture_uint, __prim_object)
|
||||||
KERNEL_TEX(uint, texture_uint, __object_node)
|
KERNEL_TEX(uint, texture_uint, __object_node)
|
||||||
|
@ -34,11 +34,14 @@ CCL_NAMESPACE_BEGIN
|
|||||||
#define __BACKGROUND__
|
#define __BACKGROUND__
|
||||||
#define __EMISSION__
|
#define __EMISSION__
|
||||||
#define __CAUSTICS_TRICKS__
|
#define __CAUSTICS_TRICKS__
|
||||||
|
#define __VISIBILITY_FLAG__
|
||||||
|
|
||||||
#ifndef __KERNEL_OPENCL__
|
#ifndef __KERNEL_OPENCL__
|
||||||
#define __SVM__
|
#define __SVM__
|
||||||
#define __TEXTURES__
|
#define __TEXTURES__
|
||||||
#define __HOLDOUT__
|
#define __HOLDOUT__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __RAY_DIFFERENTIALS__
|
#define __RAY_DIFFERENTIALS__
|
||||||
#define __CAMERA_CLIPPING__
|
#define __CAMERA_CLIPPING__
|
||||||
#define __INTERSECTION_REFINE__
|
#define __INTERSECTION_REFINE__
|
||||||
@ -76,7 +79,8 @@ enum PathRayFlag {
|
|||||||
PATH_RAY_TRANSMIT = 8,
|
PATH_RAY_TRANSMIT = 8,
|
||||||
PATH_RAY_DIFFUSE = 16,
|
PATH_RAY_DIFFUSE = 16,
|
||||||
PATH_RAY_GLOSSY = 32,
|
PATH_RAY_GLOSSY = 32,
|
||||||
PATH_RAY_SINGULAR = 64
|
PATH_RAY_SINGULAR = 64,
|
||||||
|
PATH_RAY_TRANSPARENT = 128
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Bidirectional Path Tracing */
|
/* Bidirectional Path Tracing */
|
||||||
@ -115,7 +119,7 @@ typedef enum ClosureLabel {
|
|||||||
LABEL_DIFFUSE = 128,
|
LABEL_DIFFUSE = 128,
|
||||||
LABEL_GLOSSY = 256,
|
LABEL_GLOSSY = 256,
|
||||||
LABEL_SINGULAR = 512,
|
LABEL_SINGULAR = 512,
|
||||||
LABEL_STRAIGHT = 1024,
|
LABEL_TRANSPARENT = 1024,
|
||||||
LABEL_STOP = 2048
|
LABEL_STOP = 2048
|
||||||
} ClosureLabel;
|
} ClosureLabel;
|
||||||
|
|
||||||
@ -351,9 +355,18 @@ typedef struct KernelIntegrator {
|
|||||||
float pdf_triangles;
|
float pdf_triangles;
|
||||||
float pdf_lights;
|
float pdf_lights;
|
||||||
|
|
||||||
/* path tracing */
|
/* bounces */
|
||||||
int minbounce;
|
int min_bounce;
|
||||||
int maxbounce;
|
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 */
|
/* caustics */
|
||||||
int no_caustics;
|
int no_caustics;
|
||||||
|
@ -23,6 +23,7 @@ shader node_light_path(
|
|||||||
output float IsShadowRay = 0.0,
|
output float IsShadowRay = 0.0,
|
||||||
output float IsDiffuseRay = 0.0,
|
output float IsDiffuseRay = 0.0,
|
||||||
output float IsGlossyRay = 0.0,
|
output float IsGlossyRay = 0.0,
|
||||||
|
output float IsSingularRay = 0.0,
|
||||||
output float IsReflectionRay = 0.0,
|
output float IsReflectionRay = 0.0,
|
||||||
output float IsTransmissionRay = 0.0)
|
output float IsTransmissionRay = 0.0)
|
||||||
{
|
{
|
||||||
@ -30,6 +31,7 @@ shader node_light_path(
|
|||||||
IsShadowRay = raytype("shadow");
|
IsShadowRay = raytype("shadow");
|
||||||
IsDiffuseRay = raytype("diffuse");
|
IsDiffuseRay = raytype("diffuse");
|
||||||
IsGlossyRay = raytype("glossy");
|
IsGlossyRay = raytype("glossy");
|
||||||
|
IsSingularRay = raytype("singular");
|
||||||
IsReflectionRay = raytype("reflection");
|
IsReflectionRay = raytype("reflection");
|
||||||
IsTransmissionRay = raytype("refraction");
|
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);
|
globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object);
|
||||||
|
|
||||||
/* booleans */
|
/* booleans */
|
||||||
globals->raytype = path_flag;
|
globals->raytype = path_flag; /* todo: add our own ray types */
|
||||||
globals->backfacing = (sd->flag & SD_BACKFACING);
|
globals->backfacing = (sd->flag & SD_BACKFACING);
|
||||||
|
|
||||||
/* don't know yet if we need this */
|
/* 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)
|
else if(uscattering == OSL::Labels::SINGULAR)
|
||||||
label |= LABEL_SINGULAR;
|
label |= LABEL_SINGULAR;
|
||||||
else
|
else
|
||||||
label |= LABEL_STRAIGHT;
|
label |= LABEL_TRANSPARENT;
|
||||||
|
|
||||||
/* eval + pdf */
|
/* eval + pdf */
|
||||||
eval *= flat->weight;
|
eval *= flat->weight;
|
||||||
|
@ -70,7 +70,7 @@ __device int bsdf_transparent_sample(const ShaderData *sd, float randu, float ra
|
|||||||
#endif
|
#endif
|
||||||
*pdf = 1;
|
*pdf = 1;
|
||||||
*eval = make_float3(1, 1, 1);
|
*eval = make_float3(1, 1, 1);
|
||||||
return LABEL_TRANSMIT|LABEL_STRAIGHT;
|
return LABEL_TRANSMIT|LABEL_TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
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_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_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_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_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_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;
|
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);
|
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
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ __device float voronoi_distance(NodeDistanceMetric distance_metric, float3 d, fl
|
|||||||
|
|
||||||
/* Voronoi / Worley like */
|
/* 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 */
|
/* returns distances in da and point coords in pa */
|
||||||
int xx, yy, zz, xi, yi, zi;
|
int xx, yy, zz, xi, yi, zi;
|
||||||
@ -213,7 +213,7 @@ __device float noise_wave(NodeWaveType wave, float a)
|
|||||||
|
|
||||||
/* Turbulence */
|
/* 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 fscale = 1.0f;
|
||||||
float amp = 1.0f;
|
float amp = 1.0f;
|
||||||
|
@ -104,6 +104,7 @@ typedef enum NodeLightPath {
|
|||||||
NODE_LP_shadow,
|
NODE_LP_shadow,
|
||||||
NODE_LP_diffuse,
|
NODE_LP_diffuse,
|
||||||
NODE_LP_glossy,
|
NODE_LP_glossy,
|
||||||
|
NODE_LP_singular,
|
||||||
NODE_LP_reflection,
|
NODE_LP_reflection,
|
||||||
NODE_LP_transmission,
|
NODE_LP_transmission,
|
||||||
NODE_LP_backfacing
|
NODE_LP_backfacing
|
||||||
|
@ -25,8 +25,19 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
Integrator::Integrator()
|
Integrator::Integrator()
|
||||||
{
|
{
|
||||||
minbounce = 2;
|
min_bounce = 2;
|
||||||
maxbounce = 7;
|
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;
|
no_caustics = false;
|
||||||
blur_caustics = 0.0f;
|
blur_caustics = 0.0f;
|
||||||
|
|
||||||
@ -47,13 +58,29 @@ void Integrator::device_update(Device *device, DeviceScene *dscene)
|
|||||||
KernelIntegrator *kintegrator = &dscene->data.integrator;
|
KernelIntegrator *kintegrator = &dscene->data.integrator;
|
||||||
|
|
||||||
/* integrator parameters */
|
/* integrator parameters */
|
||||||
kintegrator->minbounce = minbounce + 1;
|
kintegrator->max_bounce = max_bounce + 1;
|
||||||
kintegrator->maxbounce = maxbounce + 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->no_caustics = no_caustics;
|
||||||
kintegrator->blur_caustics = blur_caustics;
|
kintegrator->blur_caustics = blur_caustics;
|
||||||
|
|
||||||
/* sobol directions table */
|
/* 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);
|
uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions);
|
||||||
|
|
||||||
sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, 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)
|
bool Integrator::modified(const Integrator& integrator)
|
||||||
{
|
{
|
||||||
return !(minbounce == integrator.minbounce &&
|
return !(min_bounce == integrator.min_bounce &&
|
||||||
maxbounce == integrator.maxbounce &&
|
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 &&
|
no_caustics == integrator.no_caustics &&
|
||||||
blur_caustics == integrator.blur_caustics);
|
blur_caustics == integrator.blur_caustics);
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,19 @@ class Scene;
|
|||||||
|
|
||||||
class Integrator {
|
class Integrator {
|
||||||
public:
|
public:
|
||||||
int minbounce;
|
int min_bounce;
|
||||||
int maxbounce;
|
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;
|
bool no_caustics;
|
||||||
float blur_caustics;
|
float blur_caustics;
|
||||||
bool need_update;
|
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());
|
dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
|
||||||
device->tex_alloc("__tri_woop", dscene->tri_woop);
|
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()) {
|
if(pack.prim_index.size()) {
|
||||||
dscene->prim_index.reference((uint*)&pack.prim_index[0], 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);
|
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->bvh_nodes);
|
||||||
device->tex_free(dscene->object_node);
|
device->tex_free(dscene->object_node);
|
||||||
device->tex_free(dscene->tri_woop);
|
device->tex_free(dscene->tri_woop);
|
||||||
|
device->tex_free(dscene->prim_visibility);
|
||||||
device->tex_free(dscene->prim_index);
|
device->tex_free(dscene->prim_index);
|
||||||
device->tex_free(dscene->prim_object);
|
device->tex_free(dscene->prim_object);
|
||||||
device->tex_free(dscene->tri_normal);
|
device->tex_free(dscene->tri_normal);
|
||||||
@ -699,6 +704,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
|
|||||||
dscene->bvh_nodes.clear();
|
dscene->bvh_nodes.clear();
|
||||||
dscene->object_node.clear();
|
dscene->object_node.clear();
|
||||||
dscene->tri_woop.clear();
|
dscene->tri_woop.clear();
|
||||||
|
dscene->prim_visibility.clear();
|
||||||
dscene->prim_index.clear();
|
dscene->prim_index.clear();
|
||||||
dscene->prim_object.clear();
|
dscene->prim_object.clear();
|
||||||
dscene->tri_normal.clear();
|
dscene->tri_normal.clear();
|
||||||
|
@ -1117,7 +1117,7 @@ GlassBsdfNode::GlassBsdfNode()
|
|||||||
{
|
{
|
||||||
distribution = ustring("Sharp");
|
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);
|
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 Shadow Ray", SHADER_SOCKET_FLOAT);
|
||||||
add_output("Is Diffuse Ray", SHADER_SOCKET_FLOAT);
|
add_output("Is Diffuse Ray", SHADER_SOCKET_FLOAT);
|
||||||
add_output("Is Glossy 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 Transmission Ray", SHADER_SOCKET_FLOAT);
|
||||||
|
add_output("Is Singular Ray", SHADER_SOCKET_FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightPathNode::compile(SVMCompiler& compiler)
|
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);
|
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");
|
out = output("Is Reflection Ray");
|
||||||
if(!out->links.empty()) {
|
if(!out->links.empty()) {
|
||||||
compiler.stack_assign(out);
|
compiler.stack_assign(out);
|
||||||
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, out->stack_offset);
|
compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, out->stack_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
out = output("Is Transmission Ray");
|
out = output("Is Transmission Ray");
|
||||||
if(!out->links.empty()) {
|
if(!out->links.empty()) {
|
||||||
compiler.stack_assign(out);
|
compiler.stack_assign(out);
|
||||||
|
@ -33,6 +33,7 @@ Object::Object()
|
|||||||
name = "";
|
name = "";
|
||||||
mesh = NULL;
|
mesh = NULL;
|
||||||
tfm = transform_identity();
|
tfm = transform_identity();
|
||||||
|
visibility = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::~Object()
|
Object::~Object()
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
BoundBox bounds;
|
BoundBox bounds;
|
||||||
ustring name;
|
ustring name;
|
||||||
vector<ParamValue> attributes;
|
vector<ParamValue> attributes;
|
||||||
|
uint visibility;
|
||||||
|
|
||||||
Object();
|
Object();
|
||||||
~Object();
|
~Object();
|
||||||
|
@ -57,6 +57,7 @@ public:
|
|||||||
device_vector<float4> bvh_nodes;
|
device_vector<float4> bvh_nodes;
|
||||||
device_vector<uint> object_node;
|
device_vector<uint> object_node;
|
||||||
device_vector<float4> tri_woop;
|
device_vector<float4> tri_woop;
|
||||||
|
device_vector<uint> prim_visibility;
|
||||||
device_vector<uint> prim_index;
|
device_vector<uint> prim_index;
|
||||||
device_vector<uint> prim_object;
|
device_vector<uint> prim_object;
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import bpy
|
import bpy
|
||||||
cycles = bpy.context.scene.cycles
|
cycles = bpy.context.scene.cycles
|
||||||
|
|
||||||
cycles.max_bounces = 0
|
cycles.max_bounces = 8
|
||||||
cycles.min_bounces = 0
|
cycles.min_bounces = 8
|
||||||
cycles.no_caustics = False
|
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[]= {
|
static bNodeSocketType sh_node_bsdf_glass_in[]= {
|
||||||
{ SOCK_RGBA, 1, "Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
|
{ 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},
|
{ SOCK_VALUE, 1, "Fresnel", 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||||
{ -1, 0, "" }
|
{ -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 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 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 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 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},
|
{ SOCK_VALUE, 0, "Is Transmission Ray", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||||
{ -1, 0, "" }
|
{ -1, 0, "" }
|
||||||
|
Loading…
Reference in New Issue
Block a user