* Add alpha pass output, to use set Transparent option in Film panel.
* Add Holdout closure (OSL terminology), this is like the Sky option in the
  internal renderer, objects with this closure show the background / zero
  alpha.
* Add option to use Gaussian instead of Box pixel filter in the UI.
* Remove camera response curves for now, they don't really belong here in
  the pipeline, should be moved to compositor.

* Output full float values for rendering now, previously was only byte precision.
* Add a patch from Thomas to get a preview passes option, but still disabled
  because it isn't quite working right yet.
* CUDA: don't compile shader graph evaluation inline.
* Convert tabs to spaces in python files.
This commit is contained in:
Brecht Van Lommel 2011-08-28 13:55:59 +00:00
parent d48e4fc92b
commit bae896691a
63 changed files with 1018 additions and 840 deletions

@ -85,7 +85,7 @@ static void session_print_status()
static void session_init()
{
options.session = new Session(options.session_params);
options.session->reset(options.width, options.height);
options.session->reset(options.width, options.height, options.session_params.passes);
options.session->scene = options.scene;
if(options.session_params.background && !options.quiet)
@ -162,13 +162,13 @@ static void resize(int width, int height)
options.height= height;
if(options.session)
options.session->reset(options.width, options.height);
options.session->reset(options.width, options.height, options.session_params.passes);
}
void keyboard(unsigned char key)
{
if(key == 'r')
options.session->reset(options.width, options.height);
options.session->reset(options.width, options.height, options.session_params.passes);
else if(key == 27) // escape
options.session->progress.set_cancel("Cancelled");
}
@ -285,7 +285,7 @@ using namespace ccl;
int main(int argc, const char **argv)
{
path_init("../blender/intern/cycles");
path_init("../build/bin/2.59/scripts/addons/cycles/");
options_parse(argc, argv);

@ -37,50 +37,50 @@ from cycles import xml
from cycles import engine
class CyclesRender(bpy.types.RenderEngine):
bl_idname = 'CYCLES'
bl_label = "Cycles"
bl_idname = 'CYCLES'
bl_label = "Cycles"
def __init__(self):
engine.init()
self.session = None
def __del__(self):
engine.free(self)
def __init__(self):
engine.init()
self.session = None
def __del__(self):
engine.free(self)
# final render
def update(self, data, scene):
engine.create(self, data, scene)
engine.update(self, data, scene)
# final render
def update(self, data, scene):
engine.create(self, data, scene)
engine.update(self, data, scene)
def render(self):
engine.render(self)
def render(self):
engine.render(self)
# preview render
# def preview_update(self, context, id):
# pass
#
# def preview_render(self):
# pass
# viewport render
def view_update(self, context):
if not self.session:
engine.create(self, context.blend_data, context.scene,
context.region, context.space_data, context.region_data)
engine.update(self, context.blend_data, context.scene)
# preview render
# def preview_update(self, context, id):
# pass
#
# def preview_render(self):
# pass
# viewport render
def view_update(self, context):
if not self.session:
engine.create(self, context.blend_data, context.scene,
context.region, context.space_data, context.region_data)
engine.update(self, context.blend_data, context.scene)
def view_draw(self, context):
engine.draw(self, context.region, context.space_data, context.region_data)
def view_draw(self, context):
engine.draw(self, context.region, context.space_data, context.region_data)
def register():
properties.register()
ui.register()
xml.register()
bpy.utils.register_module(__name__)
properties.register()
ui.register()
xml.register()
bpy.utils.register_module(__name__)
def unregister():
xml.unregister()
ui.unregister()
properties.unregister()
bpy.utils.unregister_module(__name__)
xml.unregister()
ui.unregister()
properties.unregister()
bpy.utils.unregister_module(__name__)

@ -19,52 +19,52 @@
import bpy
def init():
import libcycles_blender as lib
import os.path
lib.init(os.path.dirname(__file__))
import libcycles_blender as lib
import os.path
lib.init(os.path.dirname(__file__))
def create(engine, data, scene, region = 0, v3d = 0, rv3d = 0):
import libcycles_blender as lib
import libcycles_blender as lib
data = data.as_pointer()
scene = scene.as_pointer()
if region:
region = region.as_pointer()
if v3d:
v3d = v3d.as_pointer()
if rv3d:
rv3d = rv3d.as_pointer()
data = data.as_pointer()
scene = scene.as_pointer()
if region:
region = region.as_pointer()
if v3d:
v3d = v3d.as_pointer()
if rv3d:
rv3d = rv3d.as_pointer()
engine.session = lib.create(engine.as_pointer(), data, scene, region, v3d, rv3d)
engine.session = lib.create(engine.as_pointer(), data, scene, region, v3d, rv3d)
def free(engine):
if "session" in dir(engine):
if engine.session:
import libcycles_blender as lib
lib.free(engine.session)
del engine.session
if "session" in dir(engine):
if engine.session:
import libcycles_blender as lib
lib.free(engine.session)
del engine.session
def render(engine):
import libcycles_blender as lib
lib.render(engine.session)
import libcycles_blender as lib
lib.render(engine.session)
def update(engine, data, scene):
import libcycles_blender as lib
lib.sync(engine.session)
import libcycles_blender as lib
lib.sync(engine.session)
def draw(engine, region, v3d, rv3d):
import libcycles_blender as lib
v3d = v3d.as_pointer()
rv3d = rv3d.as_pointer()
import libcycles_blender as lib
v3d = v3d.as_pointer()
rv3d = rv3d.as_pointer()
# draw render image
lib.draw(engine.session, v3d, rv3d)
# draw render image
lib.draw(engine.session, v3d, rv3d)
def available_devices():
import libcycles_blender as lib
return lib.available_devices()
import libcycles_blender as lib
return lib.available_devices()
def with_osl():
import libcycles_blender as lib
return lib.with_osl()
import libcycles_blender as lib
return lib.with_osl()

@ -33,81 +33,8 @@ bvh_types = (
("DYNAMIC_BVH", "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
("STATIC_BVH", "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"))
response_curves = (
("None", "None", ""),
("", "Agfa", ""),
("Agfacolor Futura 100", "Futura 100", ""),
("Agfacolor Futura 200", "Futura 200", ""),
("Agfacolor Futura 400", "Futura 400", ""),
("Agfacolor Futura II 100", "Futura II 100", ""),
("Agfacolor Futura II 200", "Futura II 200", ""),
("Agfacolor Futura II 400", "Futura II 400", ""),
("Agfacolor HDC 100 plus", "HDC 100 plus", ""),
("Agfacolor HDC 400 plus", "HDC 400 plus", ""),
("Agfacolor HDC 200 plus", "HDC 200 plus", ""),
("Agfacolor Optima II 100", "Optima II 100", ""),
("Agfacolor Optima II 200", "Optima II 200", ""),
("Agfacolor Ultra 050", "Ultra 050", ""),
("", "Agfa", ""),
("Agfacolor Vista 100", "Vista 100", ""),
("Agfacolor Vista 200", "Vista 200", ""),
("Agfacolor Vista 400", "Vista 400", ""),
("Agfacolor Vista 800", "Vista 800", ""),
("Agfachrome CT Precisa 100", "CT Precisa 100", ""),
("Agfachrome CT Precisa 200", "CT Precisa 200", ""),
("Agfachrome RSX2 050", "Agfachrome RSX2 050", ""),
("Agfachrome RSX2 100", "Agfachrome RSX2 100", ""),
("Agfachrome RSX2 200", "Agfachrome RSX2 200", ""),
("Advantix 100", "Advantix 100", ""),
("Advantix 200", "Advantix 200", ""),
("Advantix 400", "Advantix 400", ""),
("", "Kodak", ""),
("Gold 100", "Gold 100", ""),
("Gold 200", "Gold 200", ""),
("Max Zoom 800", "Max Zoom 800", ""),
("Portra 100T", "Portra 100T", ""),
("Portra 160NC", "Portra 160NC", ""),
("Portra 160VC", "Portra 160VC", ""),
("Portra 800", "Portra 800", ""),
("Portra 400VC", "Portra 400VC", ""),
("Portra 400NC", "Portra 400NC", ""),
("", "Kodak", ""),
("Ektachrome 100 plus", "Ektachrome 100 plus", ""),
("Ektachrome 320T", "Ektachrome 320T", ""),
("Ektachrome 400X", "Ektachrome 400X", ""),
("Ektachrome 64", "Ektachrome 64", ""),
("Ektachrome 64T", "Ektachrome 64T", ""),
("Ektachrome E100S", "Ektachrome E100S", ""),
("Ektachrome 100", "Ektachrome 100", ""),
("Kodachrome 200", "Kodachrome 200", ""),
("Kodachrome 25", "Kodachrome 25", ""),
("Kodachrome 64", "Kodachrome 64", ""),
#("DSCS 3151", "DSCS 3151", ""),
#("DSCS 3152", "DSCS 3152", ""),
#("DSCS 3153", "DSCS 3153", ""),
#("DSCS 3154", "DSCS 3154", ""),
#("DSCS 3155", "DSCS 3155", ""),
#("DSCS 3156", "DSCS 3156", ""),
#("KAI-0311", "KAI-0311", ""),
#("KAF-2001", "KAF-2001", ""),
#("KAF-3000", "KAF-3000", ""),
#("KAI-0372", "KAI-0372", ""),
#("KAI-1010", "KAI-1010", ""),
("", "Fujifilm", ""),
("F-125", "F-125", ""),
("F-250", "F-250", ""),
("F-400", "F-400", ""),
("FCI", "FCI", ""),
("FP2900Z", "FP2900Z", ""),
("", "Eastman", ""),
("Double X Neg 12min", "Double X Neg 12min", ""),
("Double X Neg 6min", "Double X Neg 6min", ""),
("Double X Neg 5min", "Double X Neg 5min", ""),
("Double X Neg 4min", "Double X Neg 4min", ""),
("", "Canon", ""),
("Optura 981111", "Optura 981111", ""),
("Optura 981113", "Optura 981113", ""),
("Optura 981114", "Optura 981114", ""),
("Optura 981111.SLRR", "Optura 981111.SLRR", "")
)
filter_types = (
("BOX", "Box", "Box filter"),
("GAUSSIAN", "Gaussian", "Gaussian filter"))

@ -22,99 +22,117 @@ from bpy.props import *
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")
@classmethod
def register(cls):
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")
cls.device = EnumProperty(name="Device", description="Device to use for rendering",
items=enums.devices, default="CPU")
cls.shading_system = EnumProperty(name="Shading System", description="Shading system to use for rendering",
items=enums.shading_systems, default="GPU_COMPATIBLE")
cls.shading_system = EnumProperty(name="Shading System", description="Shading system to use for rendering",
items=enums.shading_systems, default="GPU_COMPATIBLE")
cls.passes = IntProperty(name="Passes", description="Number of passes to render",
default=10, min=1, max=2147483647)
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.passes = IntProperty(name="Passes", description="Number of passes to render",
default=10, min=1, max=2147483647)
cls.preview_passes = IntProperty(name="Preview Passes", description="Number of passes to render in the viewport, unlimited if 0",
default=0, min=0, max=2147483647)
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",
default=1.0, min=0.0, max=10.0)
cls.response_curve = EnumProperty(name="Response Curve", description="Measured camera film response",
items=enums.response_curves, default="Advantix 400")
cls.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",
default=False)
cls.debug_tile_size = IntProperty(name="Tile Size", description="",
default=1024, min=1, max=4096)
cls.debug_min_size = IntProperty(name="Min Size", description="",
default=64, min=1, max=4096)
cls.debug_reset_timeout = FloatProperty(name="Reset timeout", description="",
default=0.1, min=0.01, max=10.0)
cls.debug_cancel_timeout = FloatProperty(name="Cancel timeout", description="",
default=0.1, min=0.01, max=10.0)
cls.debug_text_timeout = FloatProperty(name="Text timeout", description="",
default=1.0, min=0.01, max=10.0)
cls.filter_type = EnumProperty(name="Filter Type", description="Pixel filter type",
items=enums.filter_types, default="GAUSSIAN")
cls.filter_width = FloatProperty(name="Filter Width", description="Pixel filter width",
default=1.5, min=0.01, max=10.0)
cls.debug_bvh_type = EnumProperty(name="BVH Type", description="Choose between faster updates, or faster render",
items=enums.bvh_types, default="DYNAMIC_BVH")
cls.debug_use_spatial_splits = BoolProperty(name="Use Spatial Splits", description="Use BVH spatial splits: longer builder time, faster render",
default=False)
cls.debug_tile_size = IntProperty(name="Tile Size", description="",
default=1024, min=1, max=4096)
cls.debug_min_size = IntProperty(name="Min Size", description="",
default=64, min=1, max=4096)
cls.debug_reset_timeout = FloatProperty(name="Reset timeout", description="",
default=0.1, min=0.01, max=10.0)
cls.debug_cancel_timeout = FloatProperty(name="Cancel timeout", description="",
default=0.1, min=0.01, max=10.0)
cls.debug_text_timeout = FloatProperty(name="Text timeout", description="",
default=1.0, min=0.01, max=10.0)
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
cls.debug_bvh_type = EnumProperty(name="BVH Type", description="Choose between faster updates, or faster render",
items=enums.bvh_types, default="DYNAMIC_BVH")
cls.debug_use_spatial_splits = BoolProperty(name="Use Spatial Splits", description="Use BVH spatial splits: longer builder time, faster render",
default=False)
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
class CyclesCameraSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.Camera.cycles = PointerProperty(type=cls, name="Cycles Camera Settings", description="Cycles Camera Settings")
@classmethod
def register(cls):
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)
@classmethod
def unregister(cls):
del bpy.types.Camera.cycles
cls.lens_radius = FloatProperty(name="Lens radius", description="Lens radius for depth of field",
default=0.0, min=0.0, max=10.0)
@classmethod
def unregister(cls):
del bpy.types.Camera.cycles
class CyclesMaterialSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles Material Settings")
@classmethod
def register(cls):
bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles Material Settings")
@classmethod
def unregister(cls):
del bpy.types.Material.cycles
@classmethod
def unregister(cls):
del bpy.types.Material.cycles
class CyclesWorldSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
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 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")
@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")
cls.displacement_method = EnumProperty(name="Displacement Method", description="Method to use for the displacement",
items=enums.displacement_methods, default="BUMP")
cls.use_subdivision = BoolProperty(name="Use Subdivision", description="Subdivide mesh for rendering",
default=False)
cls.dicing_rate = FloatProperty(name="Dicing Rate", description="", default=1.0, min=0.001, max=1000.0)
cls.displacement_method = EnumProperty(name="Displacement Method", description="Method to use for the displacement",
items=enums.displacement_methods, default="BUMP")
cls.use_subdivision = BoolProperty(name="Use Subdivision", description="Subdivide mesh for rendering",
default=False)
cls.dicing_rate = FloatProperty(name="Dicing Rate", description="", default=1.0, min=0.001, max=1000.0)
@classmethod
def unregister(cls):
del bpy.types.Mesh.cycles
@classmethod
def unregister(cls):
del bpy.types.Mesh.cycles
def register():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
bpy.utils.register_class(CyclesMaterialSettings)
bpy.utils.register_class(CyclesMeshSettings)
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
bpy.utils.register_class(CyclesMaterialSettings)
bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesMeshSettings)
def unregister():
bpy.utils.unregister_class(CyclesRenderSettings)
bpy.utils.unregister_class(CyclesCameraSettings)
bpy.utils.unregister_class(CyclesMaterialSettings)
bpy.utils.unregister_class(CyclesMeshSettings)
bpy.utils.unregister_class(CyclesRenderSettings)
bpy.utils.unregister_class(CyclesCameraSettings)
bpy.utils.unregister_class(CyclesMaterialSettings)
bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings)

@ -22,494 +22,503 @@ from cycles import enums
from cycles import engine
class CyclesButtonsPanel():
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
@classmethod
def poll(cls, context):
rd = context.scene.render
return rd.engine == 'CYCLES'
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
@classmethod
def poll(cls, context):
rd = context.scene.render
return rd.engine == 'CYCLES'
class CyclesRender_PT_integrator(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Integrator"
bl_label = "Integrator"
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
scene = context.scene
cycles = scene.cycles
scene = context.scene
cscene = scene.cycles
split = layout.split()
split = layout.split()
col = split.column()
col.prop(cycles, "passes")
col.prop(cycles, "no_caustics")
col = split.column()
col.prop(cscene, "passes", text="Render Passes")
#sub = col.row()
#sub.active = cscene.preview_passes >= 1
#sub.prop(cscene, "preview_passes")
col.prop(cscene, "no_caustics")
col = split.column()
col = col.column(align=True)
col.prop(cycles, "max_bounces")
col.prop(cycles, "min_bounces")
col = split.column()
col = col.column(align=True)
col.prop(cscene, "max_bounces")
col.prop(cscene, "min_bounces")
#row = col.row()
#row.prop(cycles, "blur_caustics")
#row.active = not cycles.no_caustics
#row = col.row()
#row.prop(cscene, "blur_caustics")
#row.active = not cscene.no_caustics
class CyclesRender_PT_film(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Film"
bl_label = "Film"
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
scene = context.scene
cycles = scene.cycles
scene = context.scene
cscene = scene.cycles
split = layout.split()
split = layout.split()
split.prop(cycles, "exposure")
split.prop(cycles, "response_curve", text="")
col = split.column();
col.prop(cscene, "exposure")
col.prop(cscene, "transparent")
col = split.column()
col.prop(cscene, "filter_type", text="")
if cscene.filter_type != 'BOX':
col.prop(cscene, "filter_width", text="Width")
class CyclesRender_PT_performance(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render
cycles = scene.cycles
scene = context.scene
rd = scene.render
cscene = scene.cycles
split = layout.split()
split = layout.split()
col = split.column(align=True)
col = split.column(align=True)
col.label(text="Threads:")
col.row().prop(rd, "threads_mode", expand=True)
sub = col.column()
sub.enabled = rd.threads_mode == 'FIXED'
sub.prop(rd, "threads")
col.label(text="Threads:")
col.row().prop(rd, "threads_mode", expand=True)
sub = col.column()
sub.enabled = rd.threads_mode == 'FIXED'
sub.prop(rd, "threads")
sub = col.column(align=True)
sub.label(text="Tiles:")
sub.prop(cycles, "debug_tile_size")
sub.prop(cycles, "debug_min_size")
sub = col.column(align=True)
sub.label(text="Tiles:")
sub.prop(cscene, "debug_tile_size")
sub.prop(cscene, "debug_min_size")
col = split.column()
col = split.column()
sub = col.column(align=True)
sub.label(text="Acceleration structure:")
sub.prop(cycles, "debug_bvh_type", text="")
sub.prop(cycles, "debug_use_spatial_splits")
sub = col.column(align=True)
sub.label(text="Acceleration structure:")
sub.prop(cscene, "debug_bvh_type", text="")
sub.prop(cscene, "debug_use_spatial_splits")
class Cycles_PT_post_processing(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
rd = context.scene.render
rd = context.scene.render
split = layout.split()
split = layout.split()
col = split.column()
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
col = split.column()
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
col = split.column()
col.prop(rd, "dither_intensity", text="Dither", slider=True)
col = split.column()
col.prop(rd, "dither_intensity", text="Dither", slider=True)
class Cycles_PT_camera(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Cycles"
bl_context = "data"
bl_label = "Cycles"
bl_context = "data"
@classmethod
def poll(cls, context):
return context.camera
@classmethod
def poll(cls, context):
return context.camera
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
camera = context.camera
cycles = camera.cycles
camera = context.camera
ccamera = camera.cycles
layout.prop(cycles, "lens_radius")
layout.prop(ccamera, "lens_radius")
class Cycles_PT_context_material(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Surface"
bl_context = "material"
bl_options = {'HIDE_HEADER'}
bl_label = "Surface"
bl_context = "material"
bl_options = {'HIDE_HEADER'}
@classmethod
def poll(cls, context):
return (context.material or context.object) and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return (context.material or context.object) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mat = context.material
ob = context.object
slot = context.material_slot
space = context.space_data
mat = context.material
ob = context.object
slot = context.material_slot
space = context.space_data
if ob:
row = layout.row()
if ob:
row = layout.row()
row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
if ob.mode == 'EDIT':
row = layout.row(align=True)
row.operator("object.material_slot_assign", text="Assign")
row.operator("object.material_slot_select", text="Select")
row.operator("object.material_slot_deselect", text="Deselect")
if ob.mode == 'EDIT':
row = layout.row(align=True)
row.operator("object.material_slot_assign", text="Assign")
row.operator("object.material_slot_select", text="Select")
row.operator("object.material_slot_deselect", text="Deselect")
split = layout.split(percentage=0.65)
split = layout.split(percentage=0.65)
if ob:
split.template_ID(ob, "active_material", new="material.new")
row = split.row()
if ob:
split.template_ID(ob, "active_material", new="material.new")
row = split.row()
if slot:
row.prop(slot, "link", text="")
else:
row.label()
elif mat:
split.template_ID(space, "pin_id")
split.separator()
if slot:
row.prop(slot, "link", text="")
else:
row.label()
elif mat:
split.template_ID(space, "pin_id")
split.separator()
class Cycles_PT_mesh_displacement(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Displacement"
bl_context = "data"
bl_label = "Displacement"
bl_context = "data"
@classmethod
def poll(cls, context):
return context.mesh or context.curve or context.meta_ball
@classmethod
def poll(cls, context):
return context.mesh or context.curve or context.meta_ball
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mesh = context.mesh
curve = context.curve
mball = context.meta_ball
mesh = context.mesh
curve = context.curve
mball = context.meta_ball
if mesh:
cycles = mesh.cycles
elif curve:
cycles = curve.cycles
elif mball:
cycles = mball.cycles
if mesh:
cdata = mesh.cycles
elif curve:
cdata = curve.cycles
elif mball:
cdata = mball.cycles
layout.prop(cycles, "displacement_method", text="Method")
layout.prop(cycles, "use_subdivision");
layout.prop(cycles, "dicing_rate");
layout.prop(cdata, "displacement_method", text="Method")
layout.prop(cdata, "use_subdivision");
layout.prop(cdata, "dicing_rate");
def find_node(material, nodetype):
if material and material.node_tree:
ntree = material.node_tree
if material and material.node_tree:
ntree = material.node_tree
for node in ntree.nodes:
if type(node) is not bpy.types.NodeGroup and node.type == nodetype:
return node
return None
for node in ntree.nodes:
if type(node) is not bpy.types.NodeGroup and node.type == nodetype:
return node
return None
def find_node_input(node, name):
for input in node.inputs:
if input.name == name:
return input
return None
for input in node.inputs:
if input.name == name:
return input
return None
def panel_node_draw(layout, id, output_type, input_name):
if not id.node_tree:
layout.prop(id, "use_nodes")
return
if not id.node_tree:
layout.prop(id, "use_nodes")
return
ntree = id.node_tree
ntree = id.node_tree
node = find_node(id, output_type)
if not node:
layout.label(text="No output node.")
else:
input = find_node_input(node, input_name)
layout.template_node_view(ntree, node, input);
node = find_node(id, output_type)
if not node:
layout.label(text="No output node.")
else:
input = find_node_input(node, input_name)
layout.template_node_view(ntree, node, input);
class CyclesLamp_PT_lamp(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Surface"
bl_context = "data"
bl_label = "Surface"
bl_context = "data"
@classmethod
def poll(cls, context):
return context.lamp and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return context.lamp and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mat = context.lamp
panel_node_draw(layout, mat, 'OUTPUT_LAMP', 'Surface')
mat = context.lamp
panel_node_draw(layout, mat, 'OUTPUT_LAMP', 'Surface')
class CyclesWorld_PT_surface(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Surface"
bl_context = "world"
bl_label = "Surface"
bl_context = "world"
@classmethod
def poll(cls, context):
return context.world and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return context.world and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mat = context.world
panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Surface')
mat = context.world
panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Surface')
class CyclesWorld_PT_volume(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Volume"
bl_context = "world"
bl_label = "Volume"
bl_context = "world"
@classmethod
def poll(cls, context):
return context.world and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return context.world and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
layout.active = False
def draw(self, context):
layout = self.layout
layout.active = False
mat = context.world
panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Volume')
mat = context.world
panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Volume')
class CyclesMaterial_PT_surface(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Surface"
bl_context = "material"
bl_label = "Surface"
bl_context = "material"
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface')
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface')
class CyclesMaterial_PT_volume(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Volume"
bl_context = "material"
bl_label = "Volume"
bl_context = "material"
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
layout.active = False
def draw(self, context):
layout = self.layout
layout.active = False
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Displacement"
bl_context = "material"
bl_label = "Displacement"
bl_context = "material"
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
class CyclesMaterial_PT_settings(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Settings"
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
bl_label = "Settings"
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
# return context.material and CyclesButtonsPanel.poll(context)
return False
@classmethod
def poll(cls, context):
# return context.material and CyclesButtonsPanel.poll(context)
return False
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
mat = context.material
row = layout.row()
row.label(text="Light Group:")
row.prop(mat, "light_group", text="")
mat = context.material
row = layout.row()
row.label(text="Light Group:")
row.prop(mat, "light_group", text="")
class CyclesTexture_PT_context(CyclesButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_context = "texture"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'CYCLES'}
bl_label = ""
bl_context = "texture"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'CYCLES'}
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
tex = context.texture
space = context.space_data
pin_id = space.pin_id
use_pin_id = space.use_pin_id;
user = context.texture_user
node = context.texture_node
tex = context.texture
space = context.space_data
pin_id = space.pin_id
use_pin_id = space.use_pin_id;
user = context.texture_user
node = context.texture_node
if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
pin_id = None
if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
pin_id = None
if not pin_id:
layout.template_texture_user()
if not pin_id:
layout.template_texture_user()
if user:
layout.separator()
if user:
layout.separator()
split = layout.split(percentage=0.65)
col = split.column()
split = layout.split(percentage=0.65)
col = split.column()
if pin_id:
col.template_ID(space, "pin_id")
elif user:
col.template_ID(user, "texture", new="texture.new")
if tex:
row = split.row()
row.prop(tex, "use_nodes", icon="NODETREE", text="")
row.label()
if pin_id:
col.template_ID(space, "pin_id")
elif user:
col.template_ID(user, "texture", new="texture.new")
if tex:
row = split.row()
row.prop(tex, "use_nodes", icon="NODETREE", text="")
row.label()
if not tex.use_nodes:
split = layout.split(percentage=0.2)
split.label(text="Type:")
split.prop(tex, "type", text="")
if not tex.use_nodes:
split = layout.split(percentage=0.2)
split.label(text="Type:")
split.prop(tex, "type", text="")
class CyclesTexture_PT_nodes(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Nodes"
bl_context = "texture"
bl_label = "Nodes"
bl_context = "texture"
@classmethod
def poll(cls, context):
tex = context.texture
return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
tex = context.texture
return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
tex = context.texture
panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
tex = context.texture
panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
class CyclesTexture_PT_node(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Node"
bl_context = "texture"
bl_label = "Node"
bl_context = "texture"
@classmethod
def poll(cls, context):
node = context.texture_node
return node and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
node = context.texture_node
return node and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
node = context.texture_node
ntree = node.id_data
layout.template_node_view(ntree, node, None)
node = context.texture_node
ntree = node.id_data
layout.template_node_view(ntree, node, None)
class CyclesTexture_PT_mapping(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Mapping"
bl_context = "texture"
bl_label = "Mapping"
bl_context = "texture"
@classmethod
def poll(cls, context):
tex = context.texture
node = context.texture_node
return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
tex = context.texture
node = context.texture_node
return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
layout.label("Texture coordinate mapping goes here.");
layout.label("Translate, rotate, scale, projection, XYZ.")
def draw(self, context):
layout = self.layout
layout.label("Texture coordinate mapping goes here.");
layout.label("Translate, rotate, scale, projection, XYZ.")
class CyclesTexture_PT_color(CyclesButtonsPanel, bpy.types.Panel):
bl_label = "Color"
bl_context = "texture"
bl_label = "Color"
bl_context = "texture"
@classmethod
def poll(cls, context):
tex = context.texture
node = context.texture_node
return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
@classmethod
def poll(cls, context):
tex = context.texture
node = context.texture_node
return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
layout.label("Color modification options go here.");
layout.label("Ramp, brightness, contrast, saturation.")
def draw(self, context):
layout = self.layout
layout.label("Color modification options go here.");
layout.label("Ramp, brightness, contrast, saturation.")
def draw_device(self, context):
scene = context.scene
layout = self.layout
scene = context.scene
layout = self.layout
if scene.render.engine == "CYCLES":
cycles = scene.cycles
if scene.render.engine == "CYCLES":
cscene = scene.cycles
if 'cuda' in engine.available_devices():
layout.prop(cycles, "device")
if cycles.device == 'CPU' and engine.with_osl():
layout.prop(cycles, "shading_system")
if 'cuda' in engine.available_devices():
layout.prop(cscene, "device")
if cscene.device == 'CPU' and engine.with_osl():
layout.prop(cscene, "shading_system")
def get_panels():
return [
bpy.types.RENDER_PT_render,
bpy.types.RENDER_PT_output,
bpy.types.RENDER_PT_encoding,
bpy.types.RENDER_PT_dimensions,
bpy.types.RENDER_PT_stamp,
bpy.types.WORLD_PT_context_world,
bpy.types.DATA_PT_context_mesh,
bpy.types.DATA_PT_context_camera,
bpy.types.DATA_PT_context_lamp,
bpy.types.DATA_PT_texture_space,
bpy.types.DATA_PT_curve_texture_space,
bpy.types.DATA_PT_mball_texture_space,
bpy.types.DATA_PT_vertex_groups,
bpy.types.DATA_PT_shape_keys,
bpy.types.DATA_PT_uv_texture,
bpy.types.DATA_PT_vertex_colors,
bpy.types.DATA_PT_camera,
bpy.types.DATA_PT_camera_display,
bpy.types.DATA_PT_custom_props_mesh,
bpy.types.DATA_PT_custom_props_camera,
bpy.types.DATA_PT_custom_props_lamp,
bpy.types.TEXTURE_PT_clouds,
bpy.types.TEXTURE_PT_wood,
bpy.types.TEXTURE_PT_marble,
bpy.types.TEXTURE_PT_magic,
bpy.types.TEXTURE_PT_blend,
bpy.types.TEXTURE_PT_stucci,
bpy.types.TEXTURE_PT_image,
bpy.types.TEXTURE_PT_image_sampling,
bpy.types.TEXTURE_PT_image_mapping,
bpy.types.TEXTURE_PT_musgrave,
bpy.types.TEXTURE_PT_voronoi,
bpy.types.TEXTURE_PT_distortednoise,
bpy.types.TEXTURE_PT_voxeldata,
bpy.types.TEXTURE_PT_pointdensity,
bpy.types.TEXTURE_PT_pointdensity_turbulence]
return [
bpy.types.RENDER_PT_render,
bpy.types.RENDER_PT_output,
bpy.types.RENDER_PT_encoding,
bpy.types.RENDER_PT_dimensions,
bpy.types.RENDER_PT_stamp,
bpy.types.WORLD_PT_context_world,
bpy.types.DATA_PT_context_mesh,
bpy.types.DATA_PT_context_camera,
bpy.types.DATA_PT_context_lamp,
bpy.types.DATA_PT_texture_space,
bpy.types.DATA_PT_curve_texture_space,
bpy.types.DATA_PT_mball_texture_space,
bpy.types.DATA_PT_vertex_groups,
bpy.types.DATA_PT_shape_keys,
bpy.types.DATA_PT_uv_texture,
bpy.types.DATA_PT_vertex_colors,
bpy.types.DATA_PT_camera,
bpy.types.DATA_PT_camera_display,
bpy.types.DATA_PT_custom_props_mesh,
bpy.types.DATA_PT_custom_props_camera,
bpy.types.DATA_PT_custom_props_lamp,
bpy.types.TEXTURE_PT_clouds,
bpy.types.TEXTURE_PT_wood,
bpy.types.TEXTURE_PT_marble,
bpy.types.TEXTURE_PT_magic,
bpy.types.TEXTURE_PT_blend,
bpy.types.TEXTURE_PT_stucci,
bpy.types.TEXTURE_PT_image,
bpy.types.TEXTURE_PT_image_sampling,
bpy.types.TEXTURE_PT_image_mapping,
bpy.types.TEXTURE_PT_musgrave,
bpy.types.TEXTURE_PT_voronoi,
bpy.types.TEXTURE_PT_distortednoise,
bpy.types.TEXTURE_PT_voxeldata,
bpy.types.TEXTURE_PT_pointdensity,
bpy.types.TEXTURE_PT_pointdensity_turbulence]
def register():
bpy.types.RENDER_PT_render.append(draw_device)
bpy.types.RENDER_PT_render.append(draw_device)
for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES')
for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES')
def unregister():
bpy.types.RENDER_PT_render.remove(draw_device)
bpy.types.RENDER_PT_render.remove(draw_device)
for panel in get_panels():
panel.COMPAT_ENGINES.remove('CYCLES')
for panel in get_panels():
panel.COMPAT_ENGINES.remove('CYCLES')

@ -25,75 +25,75 @@ import xml.etree.ElementTree as etree
import xml.dom.minidom as dom
def strip(root):
root.text = None
root.tail = None
root.text = None
root.tail = None
for elem in root:
strip(elem)
for elem in root:
strip(elem)
def write(node, fname):
strip(node)
strip(node)
s = etree.tostring(node)
s = dom.parseString(s).toprettyxml()
s = etree.tostring(node)
s = dom.parseString(s).toprettyxml()
f = open(fname, "w")
f.write(s)
f = open(fname, "w")
f.write(s)
class ExportCyclesXML(bpy.types.Operator, ExportHelper):
''''''
bl_idname = "export_mesh.cycles_xml"
bl_label = "Export Cycles XML"
''''''
bl_idname = "export_mesh.cycles_xml"
bl_label = "Export Cycles XML"
filename_ext = ".xml"
filename_ext = ".xml"
@classmethod
def poll(cls, context):
return context.active_object != None
@classmethod
def poll(cls, context):
return context.active_object != None
def execute(self, context):
filepath = bpy.path.ensure_ext(self.filepath, ".xml")
def execute(self, context):
filepath = bpy.path.ensure_ext(self.filepath, ".xml")
# get mesh
scene = context.scene
object = context.object
# get mesh
scene = context.scene
object = context.object
if not object:
raise Exception("No active object")
if not object:
raise Exception("No active object")
mesh = object.to_mesh(scene, True, 'PREVIEW')
mesh = object.to_mesh(scene, True, 'PREVIEW')
if not mesh:
raise Exception("No mesh data in active object")
if not mesh:
raise Exception("No mesh data in active object")
# generate mesh node
nverts = ""
verts = ""
P = ""
# generate mesh node
nverts = ""
verts = ""
P = ""
for v in mesh.vertices:
P += "%f %f %f " % (v.co[0], v.co[1], v.co[2])
for v in mesh.vertices:
P += "%f %f %f " % (v.co[0], v.co[1], v.co[2])
for i, f in enumerate(mesh.faces):
nverts += str(len(f.vertices)) + " "
for i, f in enumerate(mesh.faces):
nverts += str(len(f.vertices)) + " "
for v in f.vertices:
verts += str(v) + " "
verts += " "
for v in f.vertices:
verts += str(v) + " "
verts += " "
node = etree.Element('mesh', attrib={'nverts': nverts, 'verts': verts, 'P': P})
# write to file
write(node, filepath)
node = etree.Element('mesh', attrib={'nverts': nverts, 'verts': verts, 'P': P})
# write to file
write(node, filepath)
return {'FINISHED'}
return {'FINISHED'}
def register():
pass
pass
def unregister():
pass
pass
if __name__ == "__main__":
register()
register()

@ -21,6 +21,7 @@
#include "camera.h"
#include "device.h"
#include "integrator.h"
#include "film.h"
#include "light.h"
#include "scene.h"
#include "session.h"
@ -94,7 +95,7 @@ void BlenderSession::create_session()
session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
/* start rendering */
session->reset(width, height);
session->reset(width, height, session_params.passes);
session->start();
}
@ -118,31 +119,17 @@ void BlenderSession::render()
void BlenderSession::write_render_result()
{
/* get result */
DisplayBuffer *display = session->display;
Device *device = session->device;
RenderBuffers *buffers = session->buffers;
float exposure = scene->film->exposure;
double total_time, pass_time;
int pass;
session->progress.get_pass(pass, total_time, pass_time);
if(!display->rgba.device_pointer)
float4 *pixels = buffers->copy_from_device(exposure, pass);
if(!pixels)
return;
/* todo: get float buffer */
device->pixels_copy_from(display->rgba, 0, width, height);
uchar4 *rgba = (uchar4*)display->rgba.data_pointer;
vector<float4> buffer(width*height);
float fac = 1.0f/255.0f;
bool color_management = b_scene.render().use_color_management();
/* normalize */
for(int i = width*height - 1; i >= 0; i--) {
uchar4 f = rgba[i];
float3 rgb = make_float3(f.x, f.y, f.z)*fac;
if(color_management)
rgb = color_srgb_to_scene_linear(rgb);
buffer[i] = make_float4(rgb.x, rgb.y, rgb.z, 1.0f);
}
struct RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, width, height);
PointerRNA rrptr;
RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
@ -150,9 +137,11 @@ void BlenderSession::write_render_result()
BL::RenderResult::layers_iterator layer;
rr.layers.begin(layer);
rna_RenderLayer_rect_set(&layer->ptr, (float*)&buffer[0]);
rna_RenderLayer_rect_set(&layer->ptr, (float*)pixels);
RE_engine_end_result((RenderEngine*)b_engine.ptr.data, rrp);
delete [] pixels;
}
void BlenderSession::synchronize()
@ -168,6 +157,9 @@ void BlenderSession::synchronize()
return;
}
/* increase passes, but never decrease */
session->set_passes(session_params.passes);
/* copy recalc flags, outside of mutex so we can decide to do the real
synchronization at a later time to not block on running updates */
sync->sync_recalc();
@ -188,7 +180,7 @@ void BlenderSession::synchronize()
/* reset if needed */
if(scene->need_reset())
session->reset(width, height);
session->reset(width, height, session_params.passes);
/* unlock */
session->scene->mutex.unlock();
@ -225,8 +217,10 @@ bool BlenderSession::draw(int w, int h)
}
/* reset if requested */
if(reset)
session->reset(width, height);
if(reset) {
SessionParams session_params = BlenderSync::get_session_params(b_scene, background);
session->reset(width, height, session_params.passes);
}
}
/* update status and progress for 3d view draw */

@ -208,6 +208,10 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *
node = new BackgroundNode();
break;
}
case BL::ShaderNode::type_HOLDOUT: {
node = new HoldoutNode();
break;
}
case BL::ShaderNode::type_BSDF_ANISOTROPIC: {
node = new WardBsdfNode();
break;
@ -594,6 +598,9 @@ void BlenderSync::sync_world()
shader->tag_update(scene);
}
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
background->transparent = get_boolean(cscene, "transparent");
if(background->modified(prevbackground))
background->tag_update(scene);

@ -18,6 +18,7 @@
#include "background.h"
#include "film.h"
#include "../render/filter.h"
#include "graph.h"
#include "integrator.h"
#include "light.h"
@ -149,10 +150,18 @@ void BlenderSync::sync_film()
Film prevfilm = *film;
film->exposure = get_float(cscene, "exposure");
film->response = get_enum_identifier(cscene, "response_curve");
if(film->modified(prevfilm))
film->tag_update(scene);
Filter *filter = scene->filter;
Filter prevfilter = *filter;
filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
if(filter->modified(prevfilter))
filter->tag_update(scene);
}
/* Scene Parameters */
@ -190,11 +199,22 @@ SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background
foreach(DeviceType dt, types)
if(dt == dtype)
params.device_type = dtype;
/* Background */
params.background = background;
/* passes */
if(background) {
params.passes = get_int(cscene, "passes");
}
else {
params.passes = get_int(cscene, "preview_passes");
if(params.passes == 0)
params.passes = INT_MAX;
}
/* other parameters */
params.threads = b_scene.render().threads();
params.background = background;
params.passes = (background)? get_int(cscene, "passes"): INT_MAX;
params.tile_size = get_int(cscene, "debug_tile_size");
params.min_size = get_int(cscene, "debug_min_size");
params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");

@ -94,18 +94,14 @@ if(WITH_CYCLES_CUDA)
set(CYCLES_CUDA_ARCH sm_10 sm_11 sm_12 sm_13 sm_20 sm_21 CACHE STRING "CUDA architectures to build for")
set(CYCLES_CUDA_MAXREG 24 CACHE STRING "CUDA maximum number of register to use")
find_path(CUDA_INCLUDES cuda.h ${CYCLES_CUDA}/include NO_DEFAULT_PATH)
find_program(CUDA_NVCC NAMES nvcc PATHS ${CYCLES_CUDA}/bin NO_DEFAULT_PATH)
if(CUDA_INCLUDES AND CUDA_NVCC)
message(STATUS "CUDA includes = ${CUDA_INCLUDES}")
if(CUDA_NVCC)
message(STATUS "CUDA nvcc = ${CUDA_NVCC}")
else()
message(STATUS "CUDA not found")
message(STATUS "CUDA compiler not found")
endif()
include_directories(${CUDA_INCLUDES})
endif()
###########################################################################

@ -86,10 +86,15 @@ void Device::pixels_free(device_memory& mem)
mem_free(mem);
}
void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height)
void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height, bool transparent)
{
pixels_copy_from(rgba, y, w, h);
if(transparent) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
glPixelZoom((float)width/(float)w, (float)height/(float)h);
glRasterPos2f(0, y);
@ -97,6 +102,9 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, in
glRasterPos2f(0.0f, 0.0f);
glPixelZoom(1.0f, 1.0f);
if(transparent)
glDisable(GL_BLEND);
}
Device *Device::create(DeviceType type, bool background, int threads)

@ -115,7 +115,7 @@ public:
/* opengl drawing */
virtual void draw_pixels(device_memory& mem, int y, int w, int h,
int width, int height);
int width, int height, bool transparent);
#ifdef WITH_NETWORK
/* networking */

@ -607,7 +607,7 @@ public:
}
}
void draw_pixels(device_memory& mem, int y, int w, int h, int width, int height)
void draw_pixels(device_memory& mem, int y, int w, int h, int width, int height, bool transparent)
{
if(!background) {
PixelMem pmem = pixel_mem_map[mem.device_pointer];
@ -621,11 +621,16 @@ public:
glEnable(GL_TEXTURE_2D);
if(transparent) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, (float)y, 0.0f);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
@ -640,6 +645,9 @@ public:
glEnd();
glPopMatrix();
if(transparent)
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
@ -649,7 +657,7 @@ public:
return;
}
Device::draw_pixels(mem, y, w, h, width, height);
Device::draw_pixels(mem, y, w, h, width, height, transparent);
}
void task_add(DeviceTask& task)

@ -244,7 +244,7 @@ public:
mem.device_pointer = tmp;
}
void draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height)
void draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height, bool transparent)
{
device_ptr tmp = rgba.device_pointer;
int i = 0, sub_h = h/devices.size();
@ -255,7 +255,7 @@ public:
/* adjust math for w/width */
rgba.device_pointer = sub.ptr_map[tmp];
sub.device->draw_pixels(rgba, sy, w, sh, width, height);
sub.device->draw_pixels(rgba, sy, w, sh, width, height, transparent);
i++;
}

@ -129,18 +129,6 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
kg->__filter_table.data = (float*)mem;
kg->__filter_table.width = width;
}
else if(strcmp(name, "__response_curve_R") == 0) {
kg->__response_curve_R.data = (float*)mem;
kg->__response_curve_R.width = width;
}
else if(strcmp(name, "__response_curve_B") == 0) {
kg->__response_curve_B.data = (float*)mem;
kg->__response_curve_B.width = width;
}
else if(strcmp(name, "__response_curve_G") == 0) {
kg->__response_curve_G.data = (float*)mem;
kg->__response_curve_G.width = width;
}
else if(strcmp(name, "__sobol_directions") == 0) {
kg->__sobol_directions.data = (uint*)mem;
kg->__sobol_directions.width = width;

@ -33,6 +33,7 @@ CCL_NAMESPACE_BEGIN
#define __device __device__ __inline__
#define __device_inline __device__ __inline__
#define __device_noinline __device__ __noinline__
#define __global
#define __shared __shared__
#define __constant

@ -30,6 +30,7 @@
/* in opencl all functions are device functions, so leave this empty */
#define __device
#define __device_inline
#define __device_noinline
/* no assert in opencl */
#define kernel_assert(cond)

@ -20,21 +20,17 @@ CCL_NAMESPACE_BEGIN
__device float4 film_map(KernelGlobals *kg, float4 irradiance, int pass)
{
float scale = kernel_data.film.exposure*(1.0f/(pass+1));
float scale = 1.0f/(float)(pass+1);
float exposure = kernel_data.film.exposure;
float4 result = irradiance*scale;
if(kernel_data.film.use_response_curve) {
/* camera response curve */
result.x = kernel_tex_interp(__response_curve_R, result.x);
result.y = kernel_tex_interp(__response_curve_G, result.y);
result.z = kernel_tex_interp(__response_curve_B, result.z);
}
else {
/* conversion to srgb */
result.x = color_scene_linear_to_srgb(result.x);
result.y = color_scene_linear_to_srgb(result.y);
result.z = color_scene_linear_to_srgb(result.z);
}
/* conversion to srgb */
result.x = color_scene_linear_to_srgb(result.x*exposure);
result.y = color_scene_linear_to_srgb(result.y*exposure);
result.z = color_scene_linear_to_srgb(result.z*exposure);
/* clamp since alpha might be > 1.0 due to russian roulette */
result.w = clamp(result.w, 0.0f, 1.0f);
return result;
}
@ -47,7 +43,7 @@ __device uchar4 film_float_to_byte(float4 color)
result.x = (uchar)clamp(color.x*255.0f, 0.0f, 255.0f);
result.y = (uchar)clamp(color.y*255.0f, 0.0f, 255.0f);
result.z = (uchar)clamp(color.z*255.0f, 0.0f, 255.0f);
result.w = 255;
result.w = (uchar)clamp(color.w*255.0f, 0.0f, 255.0f);
return result;
}

@ -105,10 +105,11 @@ __device int path_flag_from_label(int path_flag, int label)
return path_flag;
}
__device float3 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)
{
/* initialize */
float3 L = make_float3(0.0f, 0.0f, 0.0f);
float Ltransparent = 0.0f;
#ifdef __EMISSION__
float ray_pdf = 0.0f;
@ -123,14 +124,20 @@ __device float3 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
if(!scene_intersect(kg, &ray, false, &isect)) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent && (path_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);
shader_release(kg, &sd);
ShaderData sd;
shader_setup_from_background(kg, &sd, &ray);
L += throughput*shader_eval_background(kg, &sd, path_flag);
shader_release(kg, &sd);
#else
L += make_float3(0.8f, 0.8f, 0.8f);
L += make_float3(0.8f, 0.8f, 0.8f);
#endif
}
break;
}
@ -140,6 +147,22 @@ __device float3 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF);
shader_eval_surface(kg, &sd, rbsdf, path_flag);
#ifdef __HOLDOUT__
if((sd.flag & SD_HOLDOUT) && (path_flag & PATH_RAY_CAMERA)) {
float3 holdout_weight = shader_holdout_eval(kg, &sd);
if(kernel_data.background.transparent) {
Ltransparent += average(holdout_weight*throughput);
}
else {
ShaderData sd;
shader_setup_from_background(kg, &sd, &ray);
L += holdout_weight*throughput*shader_eval_background(kg, &sd, path_flag);
shader_release(kg, &sd);
}
}
#endif
#ifdef __EMISSION__
/* emission */
if(kernel_data.integrator.use_emission) {
@ -166,6 +189,12 @@ __device float3 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;
break;
}
/* sample BSDF */
float bsdf_pdf;
float3 bsdf_eval;
@ -180,8 +209,10 @@ __device float3 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
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;
}
/* modify throughput */
throughput *= bsdf_eval/bsdf_pdf;
@ -197,8 +228,10 @@ __device float3 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
float probability = path_terminate_probability(kg, bounce, throughput);
float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE);
if(terminate >= probability)
if(terminate >= probability) {
path_flag &= ~PATH_RAY_CAMERA;
break;
}
throughput /= probability;
@ -212,7 +245,7 @@ __device float3 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
#endif
}
return L;
return make_float4(L.x, L.y, L.z, 1.0f - Ltransparent);
}
__device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int pass, int x, int y)
@ -236,25 +269,19 @@ __device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __gl
/* integrate */
#ifdef __MODIFY_TP__
float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, pass);
float3 L = kernel_path_integrate(kg, &rng, pass, ray, throughput)/throughput;
float4 L = kernel_path_integrate(kg, &rng, pass, ray, throughput)/throughput;
#else
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float3 L = kernel_path_integrate(kg, &rng, pass, ray, throughput);
float4 L = kernel_path_integrate(kg, &rng, pass, ray, throughput);
#endif
/* accumulate result in output buffer */
int index = x + y*kernel_data.cam.width;
float4 result;
result.x = L.x;
result.y = L.y;
result.z = L.z;
result.w = 1.0f;
if(pass == 0)
buffer[index] = result;
buffer[index] = L;
else
buffer[index] += result;
buffer[index] += L;
path_rng_end(kg, rng_state, rng, x, y);
}

@ -342,6 +342,26 @@ __device void shader_emissive_sample(KernelGlobals *kg, ShaderData *sd,
}
}
/* Holdout */
__device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
{
#ifdef WITH_OSL
if(kg->osl.use) {
return OSLShader::holdout_eval(sd);
}
else
#endif
{
#ifdef __SVM__
if(sd->svm_closure == CLOSURE_HOLDOUT_ID)
return make_float3(1.0f, 1.0f, 1.0f);
else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
}
}
/* Surface Evaluation */
__device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,

@ -38,9 +38,6 @@ KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
/* camera/film */
KERNEL_TEX(float, texture_float, __filter_table)
KERNEL_TEX(float, texture_float, __response_curve_R)
KERNEL_TEX(float, texture_float, __response_curve_G)
KERNEL_TEX(float, texture_float, __response_curve_B)
/* sobol */
KERNEL_TEX(uint, texture_uint, __sobol_directions)

@ -37,6 +37,7 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_OPENCL__
#define __SVM__
#define __TEXTURES__
#define __HOLDOUT__
#endif
#define __RAY_DIFFERENTIALS__
#define __CAMERA_CLIPPING__
@ -194,8 +195,10 @@ struct FlatClosure {
enum ShaderDataFlag {
SD_BACKFACING = 1, /* backside of surface? */
SD_EMISSION = 2, /* have emissive closure? */
SD_BSDF_HAS_EVAL = 4, /* have non-singular bsdf closure? */
SD_BSDF_GLOSSY = 8 /* have glossy bsdf */
SD_BSDF = 4, /* have bsdf closure? */
SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
SD_HOLDOUT = 32 /* have holdout closure? */
};
typedef struct ShaderData {
@ -257,6 +260,8 @@ typedef struct ShaderData {
float emissive_sample_sum;
float volume_sample_sum;
float3 holdout_weight;
float randb;
} osl_closure;
@ -313,14 +318,14 @@ typedef struct KernelCamera {
typedef struct KernelFilm {
float exposure;
int use_response_curve;
int pad1, pad2;
int pad1, pad2, pad3;
} KernelFilm;
typedef struct KernelBackground {
/* only shader index */
int shader;
int pad1, pad2, pad3;
int transparent;
int pad1, pad2;
} KernelBackground;
typedef struct KernelSunSky {

@ -145,9 +145,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
/* scattering flags */
if(scattering == OSL::Labels::DIFFUSE)
sd->flag |= SD_BSDF_HAS_EVAL;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
else if(scattering == OSL::Labels::GLOSSY)
sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
else
sd->flag |= SD_BSDF;
/* add */
sd->osl_closure.bsdf[sd->osl_closure.num_bsdf++] = flat;
@ -170,8 +172,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->osl_closure.emissive[sd->osl_closure.num_emissive++] = flat;
break;
}
case ClosurePrimitive::BSSRDF:
case ClosurePrimitive::Holdout:
sd->osl_closure.holdout_weight += weight;
sd->flag |= SD_HOLDOUT;
break;
case ClosurePrimitive::BSSRDF:
case ClosurePrimitive::Debug:
break; /* not implemented */
case ClosurePrimitive::Background:
@ -212,6 +217,7 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
sd->osl_closure.emissive_sample_sum = 0.0f;
sd->osl_closure.num_bsdf = 0;
sd->osl_closure.num_emissive = 0;
sd->osl_closure.holdout_weight = make_float3(0.0f, 0.0f, 0.0f);
sd->osl_closure.randb = randb;
if(globals->Ci) {
@ -555,5 +561,12 @@ float3 OSLShader::volume_eval_phase(const ShaderData *sd, const float3 omega_in,
return eval;
}
/* Holdout Closure */
float3 OSLShader::holdout_eval(const ShaderData *sd)
{
return sd->osl_closure.holdout_weight;
}
CCL_NAMESPACE_END

@ -74,6 +74,7 @@ public:
float3 *eval, float3 *I, float *pdf);
static float3 volume_eval_phase(const ShaderData *sd, const float3 omega_in,
const float3 omega_out);
static float3 holdout_eval(const ShaderData *sd);
/* release */
static void release(KernelGlobals *kg, const ShaderData *sd);

@ -50,7 +50,7 @@ __device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, float3 N, float sigma)
self->m_invsigma2 = 1.0f/(sigma * sigma);
sd->svm_closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
sd->flag |= SD_BSDF_HAS_EVAL;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
}
__device void bsdf_ashikhmin_velvet_blur(ShaderData *sd, float roughness)

@ -47,7 +47,7 @@ __device void bsdf_diffuse_setup(ShaderData *sd, float3 N)
//self->m_N = N;
sd->svm_closure = CLOSURE_BSDF_DIFFUSE_ID;
sd->flag |= SD_BSDF_HAS_EVAL;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
}
__device void bsdf_diffuse_blur(ShaderData *sd, float roughness)
@ -110,7 +110,7 @@ __device void bsdf_translucent_setup(ShaderData *sd, float3 N)
//self->m_N = N;
sd->svm_closure = CLOSURE_BSDF_TRANSLUCENT_ID;
sd->flag |= SD_BSDF_HAS_EVAL;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
}
__device void bsdf_translucent_blur(ShaderData *sd, float roughness)

@ -58,7 +58,7 @@ __device void bsdf_microfacet_ggx_setup(ShaderData *sd, float3 N, float ag, floa
else
sd->svm_closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
__device void bsdf_microfacet_ggx_blur(ShaderData *sd, float roughness)
@ -278,7 +278,7 @@ __device void bsdf_microfacet_beckmann_setup(ShaderData *sd, float3 N, float ab,
else
sd->svm_closure = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
__device void bsdf_microfacet_beckmann_blur(ShaderData *sd, float roughness)

@ -47,6 +47,7 @@ __device void bsdf_reflection_setup(ShaderData *sd, float3 N)
//self->m_N = N;
sd->svm_closure = CLOSURE_BSDF_REFLECTION_ID;
sd->flag |= SD_BSDF;
}
__device void bsdf_reflection_blur(ShaderData *sd, float roughness)

@ -48,6 +48,7 @@ __device void bsdf_refraction_setup(ShaderData *sd, float3 N, float eta)
self->m_eta = eta;
sd->svm_closure = CLOSURE_BSDF_REFRACTION_ID;
sd->flag |= SD_BSDF;
}
__device void bsdf_refraction_blur(ShaderData *sd, float roughness)

@ -38,6 +38,7 @@ CCL_NAMESPACE_BEGIN
__device void bsdf_transparent_setup(ShaderData *sd)
{
sd->svm_closure = CLOSURE_BSDF_TRANSPARENT_ID;
sd->flag |= SD_BSDF;
}
__device void bsdf_transparent_blur(ShaderData *sd, float roughness)

@ -54,7 +54,7 @@ __device void bsdf_ward_setup(ShaderData *sd, float3 N, float3 T, float ax, floa
self->m_ay = clamp(ay, 1e-5f, 1.0f);
sd->svm_closure = CLOSURE_BSDF_WARD_ID;
sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
__device void bsdf_ward_blur(ShaderData *sd, float roughness)

@ -51,7 +51,7 @@ __device void bsdf_westin_backscatter_setup(ShaderData *sd, float3 N, float roug
self->m_invroughness = 1.0f/roughness;
sd->svm_closure = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
__device void bsdf_westin_backscatter_blur(ShaderData *sd, float roughness)
@ -146,7 +146,7 @@ __device void bsdf_westin_sheen_setup(ShaderData *sd, float3 N, float edginess)
self->m_edginess = edginess;
sd->svm_closure = CLOSURE_BSDF_WESTIN_SHEEN_ID;
sd->flag |= SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
__device void bsdf_westin_sheen_blur(ShaderData *sd, float roughness)

@ -148,7 +148,7 @@ CCL_NAMESPACE_BEGIN
/* Main Interpreter Loop */
__device void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type, float randb, int path_flag)
__device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type, float randb, int path_flag)
{
float stack[SVM_STACK_SIZE];
float closure_weight = 1.0f;
@ -172,6 +172,8 @@ __device void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type,
svm_node_closure_emission(sd);
else if(node.x == NODE_CLOSURE_BACKGROUND)
svm_node_closure_background(sd);
else if(node.x == NODE_CLOSURE_HOLDOUT)
svm_node_closure_holdout(sd);
else if(node.x == NODE_CLOSURE_SET_WEIGHT)
svm_node_closure_set_weight(sd, node.y, node.z, node.w);
else if(node.x == NODE_CLOSURE_WEIGHT)

@ -136,6 +136,12 @@ __device void svm_node_closure_background(ShaderData *sd)
sd->svm_closure = CLOSURE_BACKGROUND_ID;
}
__device void svm_node_closure_holdout(ShaderData *sd)
{
sd->svm_closure = CLOSURE_HOLDOUT_ID;
sd->flag |= SD_HOLDOUT;
}
/* Closure Nodes */
__device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)

@ -30,7 +30,7 @@ __device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint fro
}
case NODE_CONVERT_CF: {
float3 f = stack_load_float3(stack, from);
float g = f.x*0.2126f + f.y*0.7152f + f.z*0.0722f;
float g = linear_rgb_to_gray(f);
stack_store_float(stack, to, g);
break;
}

@ -81,7 +81,8 @@ typedef enum NodeType {
NODE_EMISSION_SET_WEIGHT_TOTAL = 4300,
NODE_ATTR_BUMP_DX = 4400,
NODE_ATTR_BUMP_DY = 4500,
NODE_TEX_ENVIRONMENT = 4600
NODE_TEX_ENVIRONMENT = 4600,
NODE_CLOSURE_HOLDOUT = 4700
} NodeType;
typedef enum NodeAttributeType {

@ -15,7 +15,6 @@ set(sources
buffers.cpp
camera.cpp
film.cpp
film_response.cpp
filter.cpp
graph.cpp
image.cpp
@ -39,7 +38,6 @@ set(headers
buffers.h
camera.h
film.h
film_response.h
filter.h
graph.h
image.h

@ -31,6 +31,7 @@ CCL_NAMESPACE_BEGIN
Background::Background()
{
transparent = false;
need_update = true;
}
@ -45,8 +46,9 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
device_free(device, dscene);
/* set shader index */
/* set shader index and transparent option */
KernelBackground *kbackground = &dscene->data.background;
kbackground->transparent = transparent;
kbackground->shader = scene->shader_manager->get_shader_id(scene->default_background);
need_update = false;
@ -58,7 +60,7 @@ void Background::device_free(Device *device, DeviceScene *dscene)
bool Background::modified(const Background& background)
{
return false;
return !(transparent == background.transparent);
}
void Background::tag_update(Scene *scene)

@ -29,6 +29,7 @@ class Scene;
class Background {
public:
bool transparent;
bool need_update;
Background();

@ -24,6 +24,7 @@
#include "util_debug.h"
#include "util_hash.h"
#include "util_image.h"
#include "util_math.h"
#include "util_opengl.h"
#include "util_time.h"
#include "util_types.h"
@ -84,6 +85,33 @@ void RenderBuffers::reset(Device *device, int width_, int height_)
device->mem_copy_to(rng_state);
}
float4 *RenderBuffers::copy_from_device(float exposure, int pass)
{
if(!buffer.device_pointer)
return NULL;
device->mem_copy_from(buffer, 0, buffer.memory_size());
float4 *out = new float4[width*height];
float4 *in = (float4*)buffer.data_pointer;
float scale = 1.0f/(float)pass;
for(int i = width*height - 1; i >= 0; i--) {
float4 rgba = in[i]*scale;
rgba.x = rgba.x*exposure;
rgba.y = rgba.y*exposure;
rgba.z = rgba.z*exposure;
/* clamp since alpha might be > 1.0 due to russian roulette */
rgba.w = clamp(rgba.w, 0.0f, 1.0f);
out[i] = rgba;
}
return out;
}
/* Display Buffer */
DisplayBuffer::DisplayBuffer(Device *device_)
@ -93,6 +121,7 @@ DisplayBuffer::DisplayBuffer(Device *device_)
height = 0;
draw_width = 0;
draw_height = 0;
transparent = true; /* todo: determine from background */
}
DisplayBuffer::~DisplayBuffer()
@ -132,10 +161,36 @@ void DisplayBuffer::draw_set(int width_, int height_)
draw_height = height_;
}
void DisplayBuffer::draw_transparency_grid()
{
GLubyte checker_stipple_sml[32*32/8] = {
255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
};
glColor4ub(50, 50, 50, 255);
glRectf(0, 0, width, height);
glEnable(GL_POLYGON_STIPPLE);
glColor4ub(55, 55, 55, 255);
glPolygonStipple(checker_stipple_sml);
glRectf(0, 0, width, height);
glDisable(GL_POLYGON_STIPPLE);
}
void DisplayBuffer::draw(Device *device)
{
if(draw_width != 0 && draw_height != 0)
device->draw_pixels(rgba, 0, draw_width, draw_height, width, height);
if(draw_width != 0 && draw_height != 0) {
if(transparent)
draw_transparency_grid();
device->draw_pixels(rgba, 0, draw_width, draw_height, width, height, transparent);
}
}
bool DisplayBuffer::draw_ready()

@ -47,6 +47,7 @@ public:
~RenderBuffers();
void reset(Device *device, int width, int height);
float4 *copy_from_device(float exposure, int pass);
protected:
void device_free();
@ -67,6 +68,8 @@ public:
with progressive render we can be using only a subset of the buffer.
if these are zero, it means nothing can be drawn yet */
int draw_width, draw_height;
/* draw alpha channel? */
bool transparent;
/* byte buffer for tonemapped result */
device_vector<uchar4> rgba;
/* mutex, must be locked manually by callers */
@ -83,6 +86,7 @@ public:
bool draw_ready();
protected:
void draw_transparency_grid();
void device_free();
Device *device;

@ -19,8 +19,6 @@
#ifndef __CAMERA_H__
#define __CAMERA_H__
#include "film_response.h"
#include "util_transform.h"
#include "util_types.h"

@ -19,30 +19,13 @@
#include "camera.h"
#include "device.h"
#include "film.h"
#include "film_response.h"
#include "scene.h"
CCL_NAMESPACE_BEGIN
static FilmResponseType find_response_type(const string& name)
{
if(name == "" || name == "None")
return FILM_RESPONSE_NONE;
for(size_t i = 0; i < FILM_RESPONSE_NUM; i++) {
FilmResponse *curve = &FILM_RESPONSE[i];
if(curve->name == name)
return (FilmResponseType)i;
}
return FILM_RESPONSE_NONE;
}
Film::Film()
{
exposure = 0.8f;
response = "Advantix 400";
last_response = "";
need_update = true;
}
@ -50,18 +33,6 @@ Film::~Film()
{
}
#if 0
static void generate_python_enum()
{
for(size_t i = 0; i < FILM_RESPONSE_NUM; i++) {
FilmResponse *curve = &FILM_RESPONSE[i];
/*if(i == 0 || strcmp(curve->brand, FILM_RESPONSE[i-1].brand))
printf("(\"\", \"%s\", \"\"),\n", curve->brand);*/
printf("(\"%s\", \"%s %s\", \"\"),\n", curve->name, curve->brand, curve->name);
}
}
#endif
void Film::device_update(Device *device, DeviceScene *dscene)
{
if(!need_update)
@ -72,57 +43,16 @@ void Film::device_update(Device *device, DeviceScene *dscene)
/* update __data */
kfilm->exposure = exposure;
FilmResponseType response_type = find_response_type(response);
/* update __response_curves */
if(response != last_response) {
device_free(device, dscene);
if(response_type != FILM_RESPONSE_NONE) {
FilmResponse *curve = &FILM_RESPONSE[response_type];
size_t response_curve_size = FILM_RESPONSE_SIZE;
dscene->response_curve_R.copy(curve->B_R, response_curve_size);
if(curve->rgb) {
dscene->response_curve_G.copy(curve->B_G, response_curve_size);
dscene->response_curve_B.copy(curve->B_B, response_curve_size);
}
else {
dscene->response_curve_G.copy(curve->B_R, response_curve_size);
dscene->response_curve_B.copy(curve->B_R, response_curve_size);
}
device->tex_alloc("__response_curve_R", dscene->response_curve_R, true);
device->tex_alloc("__response_curve_G", dscene->response_curve_G, true);
device->tex_alloc("__response_curve_B", dscene->response_curve_B, true);
}
last_response = response;
}
kfilm->use_response_curve = (response_type != FILM_RESPONSE_NONE);
need_update = false;
}
void Film::device_free(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->response_curve_R);
device->tex_free(dscene->response_curve_G);
device->tex_free(dscene->response_curve_B);
dscene->response_curve_R.clear();
dscene->response_curve_G.clear();
dscene->response_curve_B.clear();
last_response = "";
}
bool Film::modified(const Film& film)
{
return !(response == film.response &&
exposure == film.exposure &&
return !(exposure == film.exposure &&
pass == film.pass);
}

@ -29,8 +29,6 @@ class Scene;
class Film {
public:
string response;
string last_response;
float exposure;
int pass;
bool need_update;

@ -125,5 +125,16 @@ void Filter::device_free(Device *device, DeviceScene *dscene)
dscene->filter_table.clear();
}
bool Filter::modified(const Filter& filter)
{
return !(filter_type == filter.filter_type &&
filter_width == filter.filter_width);
}
void Filter::tag_update(Scene *scene)
{
need_update = true;
}
CCL_NAMESPACE_END

@ -21,6 +21,10 @@
CCL_NAMESPACE_BEGIN
class Device;
class DeviceScene;
class Scene;
typedef enum FilterType {
FILTER_BOX,
FILTER_GAUSSIAN
@ -38,6 +42,9 @@ public:
void device_update(Device *device, DeviceScene *dscene);
void device_free(Device *device, DeviceScene *dscene);
bool modified(const Filter& filter);
void tag_update(Scene *scene);
};
CCL_NAMESPACE_END

@ -392,7 +392,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
progress.set_status("Updating Mesh", "Computing attributes");
/* gather per mesh requested attributes. as meshes may have multiple
* shaders assigned, this merged the requested attributes that have
* shaders assigned, this merges the requested attributes that have
* been set per shader by the shader manager */
vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());

@ -1275,6 +1275,24 @@ void BackgroundNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_background");
}
/* Holdout Closure */
HoldoutNode::HoldoutNode()
: ShaderNode("holdout")
{
add_output("Holdout", SHADER_SOCKET_CLOSURE);
}
void HoldoutNode::compile(SVMCompiler& compiler)
{
compiler.add_node(NODE_CLOSURE_HOLDOUT, CLOSURE_HOLDOUT_ID);
}
void HoldoutNode::compile(OSLCompiler& compiler)
{
compiler.add(this, "node_holdout");
}
/* Geometry */
GeometryNode::GeometryNode()

@ -257,6 +257,11 @@ public:
SHADER_NODE_CLASS(BackgroundNode)
};
class HoldoutNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HoldoutNode)
};
class GeometryNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GeometryNode)

@ -84,11 +84,6 @@ public:
/* filter */
device_vector<float> filter_table;
/* film */
device_vector<float> response_curve_R;
device_vector<float> response_curve_G;
device_vector<float> response_curve_B;
/* integrator */
device_vector<uint> sobol_directions;

@ -52,6 +52,7 @@ Session::Session(const SessionParams& params_)
delayed_reset.do_reset = false;
delayed_reset.w = 0;
delayed_reset.h = 0;
delayed_reset.passes = 0;
display_outdated = false;
gpu_draw_ready = false;
@ -95,7 +96,7 @@ bool Session::ready_to_reset()
/* GPU Session */
void Session::reset_gpu(int w, int h)
void Session::reset_gpu(int w, int h, int passes)
{
/* block for buffer acces and reset immediately. we can't do this
in the thread, because we need to allocate an OpenGL buffer, and
@ -106,7 +107,7 @@ void Session::reset_gpu(int w, int h)
display_outdated = true;
reset_time = time_dt();
reset_(w, h);
reset_(w, h, passes);
gpu_need_tonemap = false;
gpu_need_tonemap_cond.notify_all();
@ -148,7 +149,14 @@ void Session::run_gpu()
start_time = time_dt();
reset_time = time_dt();
while(!progress.get_cancel() && tile_manager.next()) {
while(!progress.get_cancel()) {
bool done = !tile_manager.next();
if(done && params.background)
break;
/* todo: wait when done in interactive mode */
/* buffers mutex is locked entirely while rendering each
pass, and released/reacquired on each iteration to allow
reset and draw in between */
@ -193,7 +201,7 @@ void Session::run_gpu()
/* CPU Session */
void Session::reset_cpu(int w, int h)
void Session::reset_cpu(int w, int h, int passes)
{
thread_scoped_lock reset_lock(delayed_reset.mutex);
@ -202,6 +210,7 @@ void Session::reset_cpu(int w, int h)
delayed_reset.w = w;
delayed_reset.h = h;
delayed_reset.passes = passes;
delayed_reset.do_reset = true;
device->task_cancel();
}
@ -235,11 +244,18 @@ void Session::run_cpu()
thread_scoped_lock buffers_lock(buffers->mutex);
thread_scoped_lock display_lock(display->mutex);
reset_(delayed_reset.w, delayed_reset.h);
reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes);
delayed_reset.do_reset = false;
}
while(!progress.get_cancel() && tile_manager.next()) {
while(!progress.get_cancel()) {
bool done = !tile_manager.next();
if(done && params.background)
break;
/* todo: wait when done in interactive mode */
{
thread_scoped_lock buffers_lock(buffers->mutex);
@ -266,7 +282,7 @@ void Session::run_cpu()
if(delayed_reset.do_reset) {
/* reset rendering if request from main thread */
delayed_reset.do_reset = false;
reset_(delayed_reset.w, delayed_reset.h);
reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes);
}
else {
/* tonemap only if we do not reset, we don't we don't
@ -313,7 +329,7 @@ bool Session::draw(int w, int h)
return draw_cpu(w, h);
}
void Session::reset_(int w, int h)
void Session::reset_(int w, int h, int passes)
{
if(w != buffers->width || h != buffers->height) {
gpu_draw_ready = false;
@ -321,19 +337,28 @@ void Session::reset_(int w, int h)
display->reset(device, w, h);
}
tile_manager.reset(w, h);
tile_manager.reset(w, h, passes);
start_time = time_dt();
preview_time = 0.0;
pass = 0;
}
void Session::reset(int w, int h)
void Session::reset(int w, int h, int passes)
{
if(device_use_gl)
reset_gpu(w, h);
reset_gpu(w, h, passes);
else
reset_cpu(w, h);
reset_cpu(w, h, passes);
}
void Session::set_passes(int passes)
{
if(passes != params.passes) {
params.passes = passes;
tile_manager.set_passes(passes);
/* todo: awake in paused loop */
}
}
void Session::wait()

@ -107,13 +107,15 @@ public:
void wait();
bool ready_to_reset();
void reset(int w, int h);
void reset(int w, int h, int passes);
void set_passes(int passes);
protected:
struct DelayedReset {
thread_mutex mutex;
bool do_reset;
int w, h;
int passes;
} delayed_reset;
void run();
@ -123,15 +125,15 @@ protected:
void tonemap();
void path_trace(Tile& tile);
void reset_(int w, int h);
void reset_(int w, int h, int passes);
void run_cpu();
bool draw_cpu(int w, int h);
void reset_cpu(int w, int h);
void reset_cpu(int w, int h, int passes);
void run_gpu();
bool draw_gpu(int w, int h);
void reset_gpu(int w, int h);
void reset_gpu(int w, int h, int passes);
TileManager tile_manager;
bool device_use_gl;

@ -25,18 +25,17 @@ CCL_NAMESPACE_BEGIN
TileManager::TileManager(bool progressive_, int passes_, int tile_size_, int min_size_)
{
progressive = progressive_;
passes = passes_;
tile_size = tile_size_;
min_size = min_size_;
reset(0, 0);
reset(0, 0, 0);
}
TileManager::~TileManager()
{
}
void TileManager::reset(int width_, int height_)
void TileManager::reset(int width_, int height_, int passes_)
{
full_width = width_;
full_height = height_;
@ -54,6 +53,8 @@ void TileManager::reset(int width_, int height_)
}
}
passes = passes_;
state.width = 0;
state.height = 0;
state.pass = -1;
@ -61,6 +62,11 @@ void TileManager::reset(int width_, int height_)
state.tiles.clear();
}
void TileManager::set_passes(int passes_)
{
passes = passes_;
}
void TileManager::set_tiles()
{
int resolution = state.resolution;

@ -50,7 +50,8 @@ public:
TileManager(bool progressive, int passes, int tile_size, int min_size);
~TileManager();
void reset(int width, int height);
void reset(int width, int height, int passes);
void set_passes(int passes);
bool next();
bool done();

@ -60,6 +60,11 @@ __device float3 color_scene_linear_to_srgb(float3 c)
#endif
__device float linear_rgb_to_gray(float3 c)
{
return c.x*0.2126f + c.y*0.7152f + c.z*0.0722f;
}
CCL_NAMESPACE_END
#endif /* __UTIL_COLOR_H__ */

@ -30,6 +30,7 @@
#ifndef __KERNEL_GPU__
#define __device static inline
#define __device_noinline static
#define __global
#define __local
#define __shared

@ -311,6 +311,7 @@ struct ShadeResult;
#define SH_NODE_ADD_CLOSURE 156
#define SH_NODE_TEX_ENVIRONMENT 157
#define SH_NODE_OUTPUT_TEXTURE 158
#define SH_NODE_HOLDOUT 159
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

@ -3702,10 +3702,11 @@ static void registerShaderNodes(ListBase *ntypelist)
register_node_type_sh_emission(ntypelist);
register_node_type_sh_mix_closure(ntypelist);
register_node_type_sh_add_closure(ntypelist);
register_node_type_sh_holdout(ntypelist);
register_node_type_sh_output_lamp(ntypelist);
register_node_type_sh_output_material(ntypelist);
register_node_type_sh_output_texture(ntypelist);
//register_node_type_sh_output_texture(ntypelist);
register_node_type_sh_output_world(ntypelist);
register_node_type_sh_tex_blend(ntypelist);

@ -52,7 +52,7 @@ DefNode( ShaderNode, SH_NODE_COMBRGB, 0, "COMBR
DefNode( ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_MATERIAL, 0, "OUTPUT_MATERIAL",OutputMaterial, "Material Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, 0, "OUTPUT_LAMP", OutputLamp, "Lamp Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_TEXTURE, 0, "OUTPUT_TEXTURE", OutputTexture, "Texture Output", "" )
//DefNode( ShaderNode, SH_NODE_OUTPUT_TEXTURE, 0, "OUTPUT_TEXTURE", OutputTexture, "Texture Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, 0, "OUTPUT_WORLD", OutputWorld, "World Output", "" )
DefNode( ShaderNode, SH_NODE_FRESNEL, 0, "FRESNEL", Fresnel, "Fresnel", "" )
DefNode( ShaderNode, SH_NODE_MIX_CLOSURE, 0, "MIX_CLOSURE", MixClosure, "Mix Closure", "" )
@ -60,6 +60,7 @@ DefNode( ShaderNode, SH_NODE_ADD_CLOSURE, 0, "ADD_C
DefNode( ShaderNode, SH_NODE_ATTRIBUTE, 0, "ATTRIBUTE", Attribute, "Attribute", "")
DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "")
DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "")
DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Bsdf Anisotropic", "")
DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "")
DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "")

@ -128,6 +128,7 @@ set(SRC
intern/SHD_nodes/SHD_emission.c
intern/SHD_nodes/SHD_fresnel.c
intern/SHD_nodes/SHD_geometry.c
intern/SHD_nodes/SHD_holdout.c
intern/SHD_nodes/SHD_light_path.c
intern/SHD_nodes/SHD_mix_closure.c
intern/SHD_nodes/SHD_add_closure.c

@ -67,6 +67,7 @@ void register_node_type_sh_bsdf_translucent(ListBase *lb);
void register_node_type_sh_bsdf_transparent(ListBase *lb);
void register_node_type_sh_bsdf_velvet(ListBase *lb);
void register_node_type_sh_emission(ListBase *lb);
void register_node_type_sh_holdout(ListBase *lb);
void register_node_type_sh_mix_closure(ListBase *lb);
void register_node_type_sh_add_closure(ListBase *lb);

@ -0,0 +1,63 @@
/**
* $Id: SHD_output.c 32517 2010-10-16 14:32:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "../SHD_util.h"
/* **************** OUTPUT ******************** */
static bNodeSocketType sh_node_holdout_in[]= {
{ -1, 0, "" }
};
static bNodeSocketType sh_node_holdout_out[]= {
{ SOCK_CLOSURE, 0, "Holdout", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static void node_shader_exec_holdout(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
{
}
/* node type definition */
void register_node_type_sh_holdout(ListBase *lb)
{
static bNodeType ntype;
node_type_base(&ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_CLOSURE, 0,
sh_node_holdout_in, sh_node_holdout_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_exec(&ntype, node_shader_exec_holdout);
node_type_gpu(&ntype, NULL);
nodeRegisterType(lb, &ntype);
};