diff options
Diffstat (limited to 'intern/cycles')
31 files changed, 1160 insertions, 1278 deletions
diff --git a/intern/cycles/app/io_export_cycles_xml.py b/intern/cycles/app/io_export_cycles_xml.py index 7d6d85f88af..d02487aefa4 100644 --- a/intern/cycles/app/io_export_cycles_xml.py +++ b/intern/cycles/app/io_export_cycles_xml.py @@ -66,8 +66,7 @@ class RenderButtonsPanel(): @classmethod def poll(self, context): - rd = context.scene.render - return rd.engine == 'CYCLES' + return context.engine == 'CYCLES' class PHYSICS_PT_fluid_export(RenderButtonsPanel, bpy.types.Panel): diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index a2d6262fb20..353f2a1ad5b 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "Cycles Render Engine", "author": "", - "blender": (2, 76, 0), + "blender": (2, 80, 0), "location": "Info header, render engine menu", "description": "Cycles Render Engine integration", "warning": "", @@ -52,7 +52,7 @@ from . import ( class CyclesRender(bpy.types.RenderEngine): bl_idname = 'CYCLES' - bl_label = "Cycles Render" + bl_label = "Cycles" bl_use_shading_nodes = True bl_use_preview = True bl_use_exclude_layers = True @@ -66,34 +66,35 @@ class CyclesRender(bpy.types.RenderEngine): engine.free(self) # final render - def update(self, data, scene): + def update(self, data, depsgraph): if not self.session: if self.is_preview: cscene = bpy.context.scene.cycles use_osl = cscene.shading_system and cscene.device == 'CPU' - engine.create(self, data, scene, - None, None, None, use_osl) + engine.create(self, data, preview_osl=use_osl) else: - engine.create(self, data, scene) - else: - engine.reset(self, data, scene) + engine.create(self, data) + + engine.reset(self, data, depsgraph) - def render(self, scene): - engine.render(self) + def render_to_image(self, depsgraph): + engine.render(self, depsgraph) - def bake(self, scene, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result): - engine.bake(self, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result) + def bake(self, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result): + engine.bake(self, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result) # viewport render def view_update(self, context): if not self.session: - engine.create(self, context.blend_data, context.scene, + engine.create(self, context.blend_data, 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) + engine.reset(self, context.blend_data, context.depsgraph) + engine.sync(self, context.depsgraph, context.blend_data) + + def render_to_view(self, context): + engine.draw(self, context.depsgraph, context.region, context.space_data, context.region_data) def update_script_node(self, node): if engine.with_osl(): diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 1f97eff9bd0..b689c750be0 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -123,13 +123,12 @@ def exit(): _cycles.exit() -def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False): - import bpy +def create(engine, data, region=None, v3d=None, rv3d=None, preview_osl=False): import _cycles + import bpy data = data.as_pointer() userpref = bpy.context.user_preferences.as_pointer() - scene = scene.as_pointer() if region: region = region.as_pointer() if v3d: @@ -137,12 +136,8 @@ def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=Fa if rv3d: rv3d = rv3d.as_pointer() - if bpy.app.debug_value == 256: - _cycles.debug_flags_update(scene) - else: - _cycles.debug_flags_reset() - - engine.session = _cycles.create(engine.as_pointer(), userpref, data, scene, region, v3d, rv3d, preview_osl) + engine.session = _cycles.create( + engine.as_pointer(), userpref, data, region, v3d, rv3d, preview_osl) def free(engine): @@ -153,38 +148,46 @@ def free(engine): del engine.session -def render(engine): +def render(engine, depsgraph): import _cycles if hasattr(engine, "session"): - _cycles.render(engine.session) + _cycles.render(engine.session, depsgraph.as_pointer()) -def bake(engine, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result): +def bake(engine, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result): import _cycles session = getattr(engine, "session", None) if session is not None: - _cycles.bake(engine.session, obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) + _cycles.bake(engine.session, depsgraph.as_pointer(), obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) -def reset(engine, data, scene): +def reset(engine, data, depsgraph): import _cycles + import bpy + + if bpy.app.debug_value == 256: + _cycles.debug_flags_update(depsgraph.scene) + else: + _cycles.debug_flags_reset() + data = data.as_pointer() - scene = scene.as_pointer() - _cycles.reset(engine.session, data, scene) + depsgraph = depsgraph.as_pointer() + _cycles.reset(engine.session, data, depsgraph) -def update(engine, data, scene): +def sync(engine, depsgraph, data): import _cycles - _cycles.sync(engine.session) + _cycles.sync(engine.session, depsgraph.as_pointer()) -def draw(engine, region, v3d, rv3d): +def draw(engine, depsgraph, region, v3d, rv3d): import _cycles + depsgraph = depsgraph.as_pointer() v3d = v3d.as_pointer() rv3d = rv3d.as_pointer() # draw render image - _cycles.draw(engine.session, v3d, rv3d) + _cycles.draw(engine.session, depsgraph, v3d, rv3d) def available_devices(): diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 8dbd80f3747..f3403602bea 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -200,12 +200,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Pause all viewport preview renders", default=False, ) - cls.preview_active_layer = BoolProperty( - name="Preview Active Layer", - description="Preview active render layer in viewport", - default=False, - ) - cls.aa_samples = IntProperty( name="AA Samples", description="Number of antialiasing samples to render for each pixel", @@ -1201,15 +1195,15 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): def update_render_passes(self, context): scene = context.scene rd = scene.render - rl = rd.layers.active - rl.update_render_passes() + view_layer = context.view_layer + view_layer.update_render_passes() class CyclesRenderLayerSettings(bpy.types.PropertyGroup): @classmethod def register(cls): - bpy.types.SceneRenderLayer.cycles = PointerProperty( - name="Cycles SceneRenderLayer Settings", - description="Cycles SceneRenderLayer Settings", + bpy.types.ViewLayer.cycles = PointerProperty( + name="Cycles ViewLayer Settings", + description="Cycles ViewLayer Settings", type=cls, ) cls.pass_debug_bvh_traversed_nodes = BoolProperty( @@ -1333,7 +1327,7 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup): @classmethod def unregister(cls): - del bpy.types.SceneRenderLayer.cycles + del bpy.types.ViewLayer.cycles class CyclesCurveSettings(bpy.types.PropertyGroup): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 707f8756f6f..f7749c16400 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -17,6 +17,7 @@ # <pep8 compliant> import bpy +from bpy_extras.node_utils import find_node_input, find_output_node from bpy.types import ( Panel, @@ -49,8 +50,7 @@ class CyclesButtonsPanel: @classmethod def poll(cls, context): - rd = context.scene.render - return rd.engine in cls.COMPAT_ENGINES + return context.engine in cls.COMPAT_ENGINES def get_device_type(context): @@ -204,13 +204,6 @@ class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel): col.prop(cscene, "sample_all_lights_indirect") layout.row().prop(cscene, "sampling_pattern", text="Pattern") - - for rl in scene.render.layers: - if rl.samples > 0: - layout.separator() - layout.row().prop(cscene, "use_layer_samples") - break - draw_samples_info(layout, context) @@ -415,8 +408,8 @@ class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel): subsub = sub.column() subsub.active = not rd.use_save_buffers - for rl in rd.layers: - if rl.cycles.use_denoising: + for view_layer in scene.view_layers: + if view_layer.cycles.use_denoising: subsub.active = False subsub.prop(cscene, "use_progressive_refine") @@ -443,9 +436,9 @@ class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel): split.prop(cscene, "preview_start_resolution") -class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel): - bl_label = "Layer" - bl_context = "render_layer" +class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel): + bl_label = "Filter" + bl_context = "view_layer" def draw(self, context): layout = self.layout @@ -453,40 +446,22 @@ class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel): scene = context.scene rd = scene.render - rl = rd.layers.active - - split = layout.split() - - col = split.column() - col.prop(scene, "layers", text="Scene") - col.prop(rl, "layers_exclude", text="Exclude") - - col = split.column() - col.prop(rl, "layers", text="Layer") - col.prop(rl, "layers_zmask", text="Mask Layer") - - split = layout.split() + view_layer = context.view_layer - col = split.column() - col.label(text="Material:") - col.prop(rl, "material_override", text="") - col.separator() - col.prop(rl, "samples") - - col = split.column() - col.prop(rl, "use_sky", "Use Environment") - col.prop(rl, "use_ao", "Use AO") - col.prop(rl, "use_solid", "Use Surfaces") - col.prop(rl, "use_strand", "Use Hair") + col = layout.column() + col.prop(view_layer, "use_sky", "Use Environment") + col.prop(view_layer, "use_ao", "Use AO") + col.prop(view_layer, "use_solid", "Use Surfaces") + col.prop(view_layer, "use_strand", "Use Hair") if with_freestyle: row = col.row() - row.prop(rl, "use_freestyle", "Use Freestyle") + row.prop(view_layer, "use_freestyle", "Use Freestyle") row.active = rd.use_freestyle class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel): bl_label = "Passes" - bl_context = "render_layer" + bl_context = "view_layer" bl_options = {'DEFAULT_CLOSED'} def draw(self, context): @@ -496,178 +471,134 @@ class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel): scene = context.scene rd = scene.render - rl = rd.layers.active - crl = rl.cycles + view_layer = context.view_layer + cycles_view_layer = view_layer.cycles split = layout.split() col = split.column() - col.prop(rl, "use_pass_combined") - col.prop(rl, "use_pass_z") - col.prop(rl, "use_pass_mist") - col.prop(rl, "use_pass_normal") + col.prop(view_layer, "use_pass_combined") + col.prop(view_layer, "use_pass_z") + col.prop(view_layer, "use_pass_mist") + col.prop(view_layer, "use_pass_normal") row = col.row() - row.prop(rl, "use_pass_vector") + row.prop(view_layer, "use_pass_vector") row.active = not rd.use_motion_blur - col.prop(rl, "use_pass_uv") - col.prop(rl, "use_pass_object_index") - col.prop(rl, "use_pass_material_index") + col.prop(view_layer, "use_pass_uv") + col.prop(view_layer, "use_pass_object_index") + col.prop(view_layer, "use_pass_material_index") col.separator() - col.prop(rl, "use_pass_shadow") - col.prop(rl, "use_pass_ambient_occlusion") + col.prop(view_layer, "use_pass_shadow") + col.prop(view_layer, "use_pass_ambient_occlusion") col.separator() - col.prop(rl, "pass_alpha_threshold") + col.prop(view_layer, "pass_alpha_threshold") col = split.column() col.label(text="Diffuse:") row = col.row(align=True) - row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True) - row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True) - row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True) + row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True) + row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True) + row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True) col.label(text="Glossy:") row = col.row(align=True) - row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True) - row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True) - row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True) + row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True) + row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True) + row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True) col.label(text="Transmission:") row = col.row(align=True) - row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True) - row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True) - row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True) + row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True) + row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True) + row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True) col.label(text="Subsurface:") row = col.row(align=True) - row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True) - row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True) - row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True) + row.prop(view_layer, "use_pass_subsurface_direct", text="Direct", toggle=True) + row.prop(view_layer, "use_pass_subsurface_indirect", text="Indirect", toggle=True) + row.prop(view_layer, "use_pass_subsurface_color", text="Color", toggle=True) col.label(text="Volume:") row = col.row(align=True) - row.prop(crl, "use_pass_volume_direct", text="Direct", toggle=True) - row.prop(crl, "use_pass_volume_indirect", text="Indirect", toggle=True) + row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True) + row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True) col.separator() - col.prop(rl, "use_pass_emit", text="Emission") - col.prop(rl, "use_pass_environment") + col.prop(view_layer, "use_pass_emit", text="Emission") + col.prop(view_layer, "use_pass_environment") if context.scene.cycles.feature_set == 'EXPERIMENTAL': col.separator() sub = col.column() - sub.active = crl.use_denoising - sub.prop(crl, "denoising_store_passes", text="Denoising") + sub.active = cycles_view_layer.use_denoising + sub.prop(cycles_view_layer, "denoising_store_passes", text="Denoising") col = layout.column() - col.prop(crl, "pass_debug_render_time") + col.prop(cycles_view_layer, "pass_debug_render_time") if _cycles.with_cycles_debug: - col.prop(crl, "pass_debug_bvh_traversed_nodes") - col.prop(crl, "pass_debug_bvh_traversed_instances") - col.prop(crl, "pass_debug_bvh_intersections") - col.prop(crl, "pass_debug_ray_bounces") - - -class CYCLES_RENDER_PT_views(CyclesButtonsPanel, Panel): - bl_label = "Views" - bl_context = "render_layer" - bl_options = {'DEFAULT_CLOSED'} - - def draw_header(self, context): - rd = context.scene.render - self.layout.prop(rd, "use_multiview", text="") - - def draw(self, context): - layout = self.layout - - scene = context.scene - rd = scene.render - rv = rd.views.active - - layout.active = rd.use_multiview - basic_stereo = (rd.views_format == 'STEREO_3D') - - row = layout.row() - row.prop(rd, "views_format", expand=True) - - if basic_stereo: - row = layout.row() - row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2) - - row = layout.row() - row.label(text="File Suffix:") - row.prop(rv, "file_suffix", text="") - - else: - row = layout.row() - row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2) - - col = row.column(align=True) - col.operator("scene.render_view_add", icon='ZOOMIN', text="") - col.operator("scene.render_view_remove", icon='ZOOMOUT', text="") - - row = layout.row() - row.label(text="Camera Suffix:") - row.prop(rv, "camera_suffix", text="") + col.prop(cycles_view_layer, "pass_debug_bvh_traversed_nodes") + col.prop(cycles_view_layer, "pass_debug_bvh_traversed_instances") + col.prop(cycles_view_layer, "pass_debug_bvh_intersections") + col.prop(cycles_view_layer, "pass_debug_ray_bounces") class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): bl_label = "Denoising" - bl_context = "render_layer" + bl_context = "view_layer" bl_options = {'DEFAULT_CLOSED'} def draw_header(self, context): - rd = context.scene.render - rl = rd.layers.active - crl = rl.cycles - cscene = context.scene.cycles + scene = context.scene + view_layer = context.view_layer + cycles_view_layer = view_layer.cycles + cscene = scene.cycles layout = self.layout - layout.prop(crl, "use_denoising", text="") + layout.prop(cycles_view_layer, "use_denoising", text="") def draw(self, context): layout = self.layout scene = context.scene cscene = scene.cycles - rd = scene.render - rl = rd.layers.active - crl = rl.cycles + view_layer = context.view_layer + cycles_view_layer = view_layer.cycles - layout.active = crl.use_denoising + layout.active = cycles_view_layer.use_denoising split = layout.split() col = split.column() sub = col.column(align=True) - sub.prop(crl, "denoising_radius", text="Radius") - sub.prop(crl, "denoising_strength", slider=True, text="Strength") + sub.prop(cycles_view_layer, "denoising_radius", text="Radius") + sub.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength") col = split.column() sub = col.column(align=True) - sub.prop(crl, "denoising_feature_strength", slider=True, text="Feature Strength") - sub.prop(crl, "denoising_relative_pca") + sub.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength") + sub.prop(cycles_view_layer, "denoising_relative_pca") layout.separator() row = layout.row() row.label(text="Diffuse:") sub = row.row(align=True) - sub.prop(crl, "denoising_diffuse_direct", text="Direct", toggle=True) - sub.prop(crl, "denoising_diffuse_indirect", text="Indirect", toggle=True) + sub.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True) + sub.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True) row = layout.row() row.label(text="Glossy:") sub = row.row(align=True) - sub.prop(crl, "denoising_glossy_direct", text="Direct", toggle=True) - sub.prop(crl, "denoising_glossy_indirect", text="Indirect", toggle=True) + sub.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True) + sub.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True) row = layout.row() row.label(text="Transmission:") sub = row.row(align=True) - sub.prop(crl, "denoising_transmission_direct", text="Direct", toggle=True) - sub.prop(crl, "denoising_transmission_indirect", text="Indirect", toggle=True) + sub.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True) + sub.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True) row = layout.row() row.label(text="Subsurface:") sub = row.row(align=True) - sub.prop(crl, "denoising_subsurface_direct", text="Direct", toggle=True) - sub.prop(crl, "denoising_subsurface_indirect", text="Indirect", toggle=True) + sub.prop(cycles_view_layer, "denoising_subsurface_direct", text="Direct", toggle=True) + sub.prop(cycles_view_layer, "denoising_subsurface_indirect", text="Indirect", toggle=True) class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): @@ -916,43 +847,22 @@ class CYCLES_OT_use_shading_nodes(Operator): return {'FINISHED'} -def find_node(material, nodetype): - if material and material.node_tree: - ntree = material.node_tree - - active_output_node = None - for node in ntree.nodes: - if getattr(node, "type", None) == nodetype: - if getattr(node, "is_active_output", True): - return node - if not active_output_node: - active_output_node = node - return active_output_node - - return None - - -def find_node_input(node, name): - for input in node.inputs: - if input.name == name: - return input - - return None - - -def panel_node_draw(layout, id_data, output_type, input_name): +def panel_node_draw(layout, id_data, output_types, input_name): if not id_data.use_nodes: layout.operator("cycles.use_shading_nodes", icon='NODETREE') return False ntree = id_data.node_tree - node = find_node(id_data, output_type) - if not node: - layout.label(text="No output node") - else: + node = find_output_node(ntree, output_types) + if node: input = find_node_input(node, input_name) - layout.template_node_view(ntree, node, input) + if input: + layout.template_node_view(ntree, node, input) + else: + layout.label(text="Incompatible output node") + else: + layout.label(text="No output node") return True @@ -999,9 +909,9 @@ class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel): col.prop(lamp, "shape", text="") sub = col.column(align=True) - if lamp.shape == 'SQUARE': + if lamp.shape in {'SQUARE', 'DISK'}: sub.prop(lamp, "size") - elif lamp.shape == 'RECTANGLE': + elif lamp.shape in {'RECTANGLE', 'ELLIPSE'}: sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") @@ -1041,7 +951,7 @@ class CYCLES_LAMP_PT_nodes(CyclesButtonsPanel, Panel): layout = self.layout lamp = context.lamp - if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'): + if not panel_node_draw(layout, lamp, ('OUTPUT_LAMP',), 'Surface'): layout.prop(lamp, "color") @@ -1096,7 +1006,7 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel): world = context.world - if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'): + if not panel_node_draw(layout, world, ('OUTPUT_WORLD',), 'Surface'): layout.prop(world, "horizon_color", text="Color") @@ -1114,7 +1024,7 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel): layout = self.layout world = context.world - panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume') + panel_node_draw(layout, world, ('OUTPUT_WORLD',), 'Volume') class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel): @@ -1151,8 +1061,8 @@ class CYCLES_WORLD_PT_mist(CyclesButtonsPanel, Panel): def poll(cls, context): if CyclesButtonsPanel.poll(context): if context.world: - for rl in context.scene.render.layers: - if rl.use_pass_mist: + for view_layer in context.scene.view_layers: + if view_layer.use_pass_mist: return True return False @@ -1259,7 +1169,7 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel): layout = self.layout mat = context.material - if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'): + if not panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Surface'): layout.prop(mat, "diffuse_color") @@ -1279,7 +1189,7 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel): mat = context.material # cmat = mat.cycles - panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume') + panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Volume') class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel): @@ -1295,7 +1205,7 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel): layout = self.layout mat = context.material - panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement') + panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Displacement') class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel): @@ -1354,175 +1264,9 @@ class CYCLES_MATERIAL_PT_viewport(CyclesButtonsPanel, Panel): col.prop(mat, "diffuse_color", text="") col.prop(mat, "alpha") - col.separator() - col.label("Alpha:") - col.prop(mat.game_settings, "alpha_blend", text="") - col = split.column(align=True) col.label("Specular:") col.prop(mat, "specular_color", text="") - col.prop(mat, "specular_hardness", text="Hardness") - - -class CYCLES_TEXTURE_PT_context(CyclesButtonsPanel, Panel): - bl_label = "" - bl_context = "texture" - bl_options = {'HIDE_HEADER'} - COMPAT_ENGINES = {'CYCLES'} - - 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 - - space.use_limited_texture_context = False - - if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)): - pin_id = None - - if not pin_id: - layout.template_texture_user() - - if user or pin_id: - layout.separator() - - split = layout.split(percentage=0.65) - col = split.column() - - if pin_id: - col.template_ID(space, "pin_id") - else: - propname = context.texture_user_property.identifier - col.template_ID(user, propname, new="texture.new") - - if tex: - split = layout.split(percentage=0.2) - split.label(text="Type:") - split.prop(tex, "type", text="") - - -class CYCLES_TEXTURE_PT_node(CyclesButtonsPanel, Panel): - bl_label = "Node" - bl_context = "texture" - - @classmethod - def poll(cls, context): - node = context.texture_node - return node and CyclesButtonsPanel.poll(context) - - def draw(self, context): - layout = self.layout - - node = context.texture_node - ntree = node.id_data - layout.template_node_view(ntree, node, None) - - -class CYCLES_TEXTURE_PT_mapping(CyclesButtonsPanel, Panel): - bl_label = "Mapping" - bl_context = "texture" - - @classmethod - def poll(cls, context): - node = context.texture_node - # TODO(sergey): perform a faster/nicer check? - return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context) - - def draw(self, context): - layout = self.layout - - node = context.texture_node - - mapping = node.texture_mapping - - layout.prop(mapping, "vector_type", expand=True) - - row = layout.row() - - row.column().prop(mapping, "translation") - row.column().prop(mapping, "rotation") - row.column().prop(mapping, "scale") - - layout.label(text="Projection:") - - row = layout.row() - row.prop(mapping, "mapping_x", text="") - row.prop(mapping, "mapping_y", text="") - row.prop(mapping, "mapping_z", text="") - - -class CYCLES_TEXTURE_PT_colors(CyclesButtonsPanel, Panel): - bl_label = "Color" - bl_context = "texture" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - # node = context.texture_node - return False - # return node and CyclesButtonsPanel.poll(context) - - def draw(self, context): - layout = self.layout - - node = context.texture_node - - mapping = node.color_mapping - - split = layout.split() - - col = split.column() - col.label(text="Blend:") - col.prop(mapping, "blend_type", text="") - col.prop(mapping, "blend_factor", text="Factor") - col.prop(mapping, "blend_color", text="") - - col = split.column() - col.label(text="Adjust:") - col.prop(mapping, "brightness") - col.prop(mapping, "contrast") - col.prop(mapping, "saturation") - - layout.separator() - - layout.prop(mapping, "use_color_ramp", text="Ramp") - if mapping.use_color_ramp: - layout.template_color_ramp(mapping, "color_ramp", expand=True) - - -class CYCLES_PARTICLE_PT_textures(CyclesButtonsPanel, Panel): - bl_label = "Textures" - bl_context = "particle" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - psys = context.particle_system - return psys and CyclesButtonsPanel.poll(context) - - def draw(self, context): - layout = self.layout - - psys = context.particle_system - part = psys.settings - - row = layout.row() - row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2) - - col = row.column(align=True) - col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP' - col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN' - col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="") - - if not part.active_texture: - layout.template_ID(part, "active_texture", new="texture.new") - else: - slot = part.texture_slots[part.active_texture_index] - layout.template_ID(slot, "texture", new="texture.new") class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel): @@ -1537,66 +1281,83 @@ class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel): scene = context.scene cscene = scene.cycles cbk = scene.render.bake + rd = scene.render - layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type + if rd.use_bake_multires: + layout.operator("object.bake_image", icon='RENDER_STILL') + else: + layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type col = layout.column() - col.prop(cscene, "bake_type") + col.prop(rd, "use_bake_multires") + if rd.use_bake_multires: + col.prop(rd, "bake_type") - col = layout.column() + split = layout.split() + + col = split.column() + col.prop(rd, "bake_margin") + col.prop(rd, "use_bake_clear") - if cscene.bake_type == 'NORMAL': - col.prop(cbk, "normal_space", text="Space") + col = split.column() + if rd.bake_type == 'DISPLACEMENT': + col.prop(rd, "use_bake_lores_mesh") + else: + col.prop(cscene, "bake_type") - row = col.row(align=True) - row.label(text="Swizzle:") - row.prop(cbk, "normal_r", text="") - row.prop(cbk, "normal_g", text="") - row.prop(cbk, "normal_b", text="") + col = layout.column() - elif cscene.bake_type == 'COMBINED': - row = col.row(align=True) - row.prop(cbk, "use_pass_direct", toggle=True) - row.prop(cbk, "use_pass_indirect", toggle=True) + if cscene.bake_type == 'NORMAL': + col.prop(cbk, "normal_space", text="Space") - split = col.split() - split.active = cbk.use_pass_direct or cbk.use_pass_indirect + row = col.row(align=True) + row.label(text="Swizzle:") + row.prop(cbk, "normal_r", text="") + row.prop(cbk, "normal_g", text="") + row.prop(cbk, "normal_b", text="") - col = split.column() - col.prop(cbk, "use_pass_diffuse") - col.prop(cbk, "use_pass_glossy") - col.prop(cbk, "use_pass_transmission") + elif cscene.bake_type == 'COMBINED': + row = col.row(align=True) + row.prop(cbk, "use_pass_direct", toggle=True) + row.prop(cbk, "use_pass_indirect", toggle=True) - col = split.column() - col.prop(cbk, "use_pass_subsurface") - col.prop(cbk, "use_pass_ambient_occlusion") - col.prop(cbk, "use_pass_emit") + split = col.split() + split.active = cbk.use_pass_direct or cbk.use_pass_indirect - elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}: - row = col.row(align=True) - row.prop(cbk, "use_pass_direct", toggle=True) - row.prop(cbk, "use_pass_indirect", toggle=True) - row.prop(cbk, "use_pass_color", toggle=True) + col = split.column() + col.prop(cbk, "use_pass_diffuse") + col.prop(cbk, "use_pass_glossy") + col.prop(cbk, "use_pass_transmission") - layout.separator() + col = split.column() + col.prop(cbk, "use_pass_subsurface") + col.prop(cbk, "use_pass_ambient_occlusion") + col.prop(cbk, "use_pass_emit") - split = layout.split() + elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}: + row = col.row(align=True) + row.prop(cbk, "use_pass_direct", toggle=True) + row.prop(cbk, "use_pass_indirect", toggle=True) + row.prop(cbk, "use_pass_color", toggle=True) - col = split.column() - col.prop(cbk, "margin") - col.prop(cbk, "use_clear") + layout.separator() - col = split.column() - col.prop(cbk, "use_selected_to_active") - sub = col.column() - sub.active = cbk.use_selected_to_active - sub.prop(cbk, "use_cage", text="Cage") - if cbk.use_cage: - sub.prop(cbk, "cage_extrusion", text="Extrusion") - sub.prop_search(cbk, "cage_object", scene, "objects", text="") - else: - sub.prop(cbk, "cage_extrusion", text="Ray Distance") + split = layout.split() + col = split.column() + col.prop(cbk, "margin") + col.prop(cbk, "use_clear") + + col = split.column() + col.prop(cbk, "use_selected_to_active") + sub = col.column() + sub.active = cbk.use_selected_to_active + sub.prop(cbk, "use_cage", text="Cage") + if cbk.use_cage: + sub.prop(cbk, "cage_extrusion", text="Extrusion") + sub.prop_search(cbk, "cage_object", scene, "objects", text="") + else: + sub.prop(cbk, "cage_extrusion", text="Ray Distance") class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel): bl_label = "Debug" @@ -1704,6 +1465,7 @@ class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel): row.prop(rd, "simplify_subdivision", text="Viewport") row.prop(rd, "simplify_subdivision_render", text="Render") + col = layout.column(align=True) col.label(text="Child Particles") row = col.row(align=True) @@ -1743,11 +1505,13 @@ def draw_device(self, context): scene = context.scene layout = self.layout - if scene.render.engine == 'CYCLES': + if context.engine == 'CYCLES': from . import engine cscene = scene.cycles - layout.prop(cscene, "feature_set") + split = layout.split(percentage=1 / 3) + split.label("Feature Set:") + split.prop(cscene, "feature_set", text="") split = layout.split(percentage=1 / 3) split.label("Device:") @@ -1763,14 +1527,11 @@ def draw_pause(self, context): layout = self.layout scene = context.scene - if scene.render.engine == "CYCLES": + if context.engine == "CYCLES": view = context.space_data - if view.viewport_shade == 'RENDERED': - cscene = scene.cycles - layername = scene.render.layers.active.name - layout.prop(cscene, "preview_pause", icon="PAUSE", text="") - layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername) + cscene = scene.cycles + layout.prop(cscene, "preview_pause", icon="PAUSE", text="") def get_panels(): @@ -1780,47 +1541,13 @@ def get_panels(): 'DATA_PT_falloff_curve', 'DATA_PT_lamp', 'DATA_PT_preview', - 'DATA_PT_shadow', 'DATA_PT_spot', - 'DATA_PT_sunsky', 'MATERIAL_PT_context_material', - 'MATERIAL_PT_diffuse', - 'MATERIAL_PT_flare', - 'MATERIAL_PT_halo', - 'MATERIAL_PT_mirror', - 'MATERIAL_PT_options', - 'MATERIAL_PT_pipeline', 'MATERIAL_PT_preview', - 'MATERIAL_PT_shading', - 'MATERIAL_PT_shadow', - 'MATERIAL_PT_specular', - 'MATERIAL_PT_sss', - 'MATERIAL_PT_strand', - 'MATERIAL_PT_transp', - 'MATERIAL_PT_volume_density', - 'MATERIAL_PT_volume_integration', - 'MATERIAL_PT_volume_lighting', - 'MATERIAL_PT_volume_options', - 'MATERIAL_PT_volume_shading', - 'MATERIAL_PT_volume_transp', - 'RENDERLAYER_PT_layer_options', - 'RENDERLAYER_PT_layer_passes', - 'RENDERLAYER_PT_views', - 'RENDER_PT_antialiasing', - 'RENDER_PT_bake', - 'RENDER_PT_motion_blur', - 'RENDER_PT_performance', + 'VIEWLAYER_PT_filter', + 'VIEWLAYER_PT_layer_passes', 'RENDER_PT_post_processing', - 'RENDER_PT_shading', 'SCENE_PT_simplify', - 'TEXTURE_PT_context_texture', - 'WORLD_PT_ambient_occlusion', - 'WORLD_PT_environment_lighting', - 'WORLD_PT_gather', - 'WORLD_PT_indirect_lighting', - 'WORLD_PT_mist', - 'WORLD_PT_preview', - 'WORLD_PT_world' } panels = [] @@ -1841,9 +1568,8 @@ classes = ( CYCLES_RENDER_PT_motion_blur, CYCLES_RENDER_PT_film, CYCLES_RENDER_PT_performance, - CYCLES_RENDER_PT_layer_options, + CYCLES_RENDER_PT_filter, CYCLES_RENDER_PT_layer_passes, - CYCLES_RENDER_PT_views, CYCLES_RENDER_PT_denoising, CYCLES_PT_post_processing, CYCLES_CAMERA_PT_dof, @@ -1868,11 +1594,6 @@ classes = ( CYCLES_MATERIAL_PT_displacement, CYCLES_MATERIAL_PT_settings, CYCLES_MATERIAL_PT_viewport, - CYCLES_TEXTURE_PT_context, - CYCLES_TEXTURE_PT_node, - CYCLES_TEXTURE_PT_mapping, - CYCLES_TEXTURE_PT_colors, - CYCLES_PARTICLE_PT_textures, CYCLES_RENDER_PT_bake, CYCLES_RENDER_PT_debug, CYCLES_PARTICLE_PT_curve_settings, @@ -1883,7 +1604,7 @@ classes = ( def register(): from bpy.utils import register_class - bpy.types.RENDER_PT_render.append(draw_device) + bpy.types.RENDER_PT_context.append(draw_device) bpy.types.VIEW3D_HT_header.append(draw_pause) for panel in get_panels(): @@ -1896,7 +1617,7 @@ def register(): def unregister(): from bpy.utils import unregister_class - bpy.types.RENDER_PT_render.remove(draw_device) + bpy.types.RENDER_PT_context.remove(draw_device) bpy.types.VIEW3D_HT_header.remove(draw_pause) for panel in get_panels(): diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index 292f0a1fa90..2689fa63ca8 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -417,7 +417,8 @@ def do_versions(self): if not cscene.is_property_set("sample_clamp_indirect"): cscene.sample_clamp_indirect = 0.0 - if bpy.data.version <= (2, 79, 1): + if bpy.data.version <= (2, 79, 1) or \ + (bpy.data.version >= (2, 80, 0) and bpy.data.version <= (2, 80, 3)): displacement_nodes_insert() if bpy.data.version <= (2, 79, 2): @@ -428,6 +429,7 @@ def do_versions(self): foreach_cycles_node(displacement_principled_nodes) - if bpy.data.version <= (2, 79, 3): + if bpy.data.version <= (2, 79, 3) or \ + (bpy.data.version >= (2, 80, 0) and bpy.data.version <= (2, 80, 4)): # Switch to squared roughness convention square_roughness_nodes_insert() diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index f00ade320e7..c7d37527d78 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -95,8 +95,8 @@ static void blender_camera_init(BlenderCamera *bcam, bcam->type = CAMERA_PERSPECTIVE; bcam->zoom = 1.0f; bcam->pixelaspect = make_float2(1.0f, 1.0f); - bcam->sensor_width = 32.0f; - bcam->sensor_height = 18.0f; + bcam->sensor_width = 36.0f; + bcam->sensor_height = 24.0f; bcam->sensor_fit = BlenderCamera::AUTO; bcam->shuttertime = 1.0f; bcam->motion_position = Camera::MOTION_POSITION_CENTER; diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index daccb89f5a2..f2bb1b0158c 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -326,18 +326,6 @@ static bool ObtainCacheParticleVcol(Mesh *mesh, return true; } -static void set_resolution(BL::Object *b_ob, BL::Scene *scene, bool render) -{ - BL::Object::modifiers_iterator b_mod; - for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { - if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) { - BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); - BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); - b_psys.set_resolution(*scene, *b_ob, (render)? 2: 1); - } - } -} - static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam, bool is_ortho) { @@ -919,9 +907,6 @@ void BlenderSync::sync_curves(Mesh *mesh, ParticleCurveData CData; - if(!preview) - set_resolution(&b_ob, &b_scene, true); - ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); /* add hair geometry to mesh */ @@ -1064,9 +1049,6 @@ void BlenderSync::sync_curves(Mesh *mesh, } } - if(!preview) - set_resolution(&b_ob, &b_scene, false); - mesh->compute_bounds(); } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 7d6ca18b074..03d24c04e2a 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -561,7 +561,7 @@ static void attr_create_subd_uv_map(Scene *scene, int i = 0; for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) { - bool active_render = b_mesh.uv_textures[i].active_render(); + bool active_render = l->active_render(); AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring uv_name = ustring(l->name().c_str()); AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT @@ -1069,7 +1069,9 @@ static void sync_mesh_fluid_motion(BL::Object& b_ob, Scene *scene, Mesh *mesh) } } -Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, +Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph, + BL::Object& b_ob, + BL::Object& b_ob_instance, bool object_updated, bool hide_tris) { @@ -1083,8 +1085,8 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, /* test if we can instance or if the object is modified */ BL::ID b_ob_data = b_ob.data(); - BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data; - BL::Material material_override = render_layer.material_override; + BL::ID key = (BKE_object_is_modified(b_ob))? b_ob_instance: b_ob_data; + BL::Material material_override = view_layer.material_override; /* find shader indices */ vector<Shader*> used_shaders; @@ -1109,10 +1111,10 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, /* test if we need to sync */ int requested_geometry_flags = Mesh::GEOMETRY_NONE; - if(render_layer.use_surfaces) { + if(view_layer.use_surfaces) { requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; } - if(render_layer.use_hair) { + if(view_layer.use_hair) { requested_geometry_flags |= Mesh::GEOMETRY_CURVES; } Mesh *mesh; @@ -1186,14 +1188,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, - b_scene, - true, - !preview, + b_depsgraph, + false, need_undeformed, mesh->subdivision_type); if(b_mesh) { - if(render_layer.use_surfaces && !hide_tris) { + if(view_layer.use_surfaces && !hide_tris) { if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, dicing_rate, max_subdivisions); @@ -1203,7 +1204,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); } - if(render_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) + if(view_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) sync_curves(mesh, b_mesh, b_ob, false); if(can_free_caches) { @@ -1231,7 +1232,8 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, return mesh; } -void BlenderSync::sync_mesh_motion(BL::Object& b_ob, +void BlenderSync::sync_mesh_motion(BL::Depsgraph& b_depsgraph, + BL::Object& b_ob, Object *object, float motion_time) { @@ -1274,9 +1276,8 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, /* get derived mesh */ b_mesh = object_to_mesh(b_data, b_ob, - b_scene, - true, - !preview, + b_depsgraph, + false, false, Mesh::SUBDIVISION_NONE); } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 077ceb4ebef..090682c8e14 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -112,13 +112,14 @@ static uint object_ray_visibility(BL::Object& b_ob) void BlenderSync::sync_light(BL::Object& b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object& b_ob, - BL::DupliObject& b_dupli_ob, + BL::Object& b_ob_instance, + int random_id, Transform& tfm, bool *use_portal) { /* test if we need to sync */ Light *light; - ObjectKey key(b_parent, persistent_id, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob_instance); if(!light_map.sync(&light, b_ob, b_parent, key)) { if(light->is_portal) @@ -161,10 +162,24 @@ void BlenderSync::sync_light(BL::Object& b_parent, light->axisu = transform_get_column(&tfm, 0); light->axisv = transform_get_column(&tfm, 1); light->sizeu = b_area_lamp.size(); - if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE) - light->sizev = b_area_lamp.size_y(); - else - light->sizev = light->sizeu; + switch(b_area_lamp.shape()) { + case BL::AreaLamp::shape_SQUARE: + light->sizev = light->sizeu; + light->round = false; + break; + case BL::AreaLamp::shape_RECTANGLE: + light->sizev = b_area_lamp.size_y(); + light->round = false; + break; + case BL::AreaLamp::shape_DISK: + light->sizev = light->sizeu; + light->round = true; + break; + case BL::AreaLamp::shape_ELLIPSE: + light->sizev = b_area_lamp.size_y(); + light->round = true; + break; + } light->type = LIGHT_AREA; break; } @@ -194,8 +209,8 @@ void BlenderSync::sync_light(BL::Object& b_parent, light->max_bounces = get_int(clamp, "max_bounces"); - if(b_dupli_ob) { - light->random_id = b_dupli_ob.random_id(); + if(b_ob != b_ob_instance) { + light->random_id = random_id; } else { light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0); @@ -262,24 +277,43 @@ void BlenderSync::sync_background_light(bool use_portal) /* Object */ -Object *BlenderSync::sync_object(BL::Object& b_parent, - int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::DupliObject& b_dupli_ob, - Transform& tfm, +Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph, + BL::Depsgraph::duplis_iterator& b_dupli_iter, uint layer_flag, float motion_time, bool hide_tris, BlenderObjectCulling& culling, bool *use_portal) { - BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); - bool motion = motion_time != 0.0f; - + const bool is_instance = b_dupli_iter->is_instance(); + BL::Object b_ob = b_dupli_iter->object(); + BL::Object b_parent = is_instance ? b_dupli_iter->parent() + : b_dupli_iter->object(); + BL::Object b_ob_instance = is_instance ? b_dupli_iter->instance_object() + : b_ob; + const bool motion = motion_time != 0.0f; + /*const*/ Transform tfm = get_transform(b_ob.matrix_world()); + int *persistent_id = NULL; + BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array; + if(is_instance) { + persistent_id_array = b_dupli_iter->persistent_id(); + persistent_id = persistent_id_array.data; + } + /* light is handled separately */ if(object_is_light(b_ob)) { /* don't use lamps for excluded layers used as mask layer */ - if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer))) - sync_light(b_parent, persistent_id, b_ob, b_dupli_ob, tfm, use_portal); + if(!motion && !((layer_flag & view_layer.holdout_layer) && + (layer_flag & view_layer.exclude_layer))) + { + sync_light(b_parent, + persistent_id, + b_ob, + b_ob_instance, + is_instance ? b_dupli_iter->random_id() : 0, + tfm, + use_portal); + } return NULL; } @@ -296,7 +330,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, /* Visibility flags for both parent and child. */ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); - bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0 || + bool use_holdout = (layer_flag & view_layer.holdout_layer) != 0 || get_boolean(cobject, "is_holdout"); uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY; @@ -305,12 +339,12 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, } /* Make holdout objects on excluded layer invisible for non-camera rays. */ - if(use_holdout && (layer_flag & render_layer.exclude_layer)) { + if(use_holdout && (layer_flag & view_layer.exclude_layer)) { visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA); } /* Hide objects not on render layer from camera rays. */ - if(!(layer_flag & render_layer.layer)) { + if(!(layer_flag & view_layer.layer)) { visibility &= ~PATH_RAY_CAMERA; } @@ -320,7 +354,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, } /* key to lookup object */ - ObjectKey key(b_parent, persistent_id, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob_instance); Object *object; /* motion vector case */ @@ -336,7 +370,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, /* mesh deformation */ if(object->mesh) - sync_mesh_motion(b_ob, object, motion_time); + sync_mesh_motion(b_depsgraph, b_ob, object, motion_time); } return object; @@ -349,7 +383,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, object_updated = true; /* mesh sync */ - object->mesh = sync_mesh(b_ob, object_updated, hide_tris); + object->mesh = sync_mesh(b_depsgraph, b_ob, b_ob_instance, object_updated, hide_tris); /* special case not tracked by object update flags */ @@ -413,10 +447,13 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, } /* dupli texture coordinates and random_id */ - if(b_dupli_ob) { - object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f); - object->dupli_uv = get_float2(b_dupli_ob.uv()); - object->random_id = b_dupli_ob.random_id(); + if(is_instance) { + object->dupli_generated = 0.5f*get_float3(b_dupli_iter->orco()) - make_float3(0.5f, 0.5f, 0.5f); + object->dupli_uv = get_float2(b_dupli_iter->uv()); + object->random_id = b_dupli_iter->random_id(); + + /* Sync possible particle data. */ + sync_dupli_particle(b_ob, *b_dupli_iter, object); } else { object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f); @@ -451,6 +488,7 @@ static bool object_render_hide(BL::Object& b_ob, BL::Object::particle_systems_iterator b_psys; bool hair_present = false; + bool has_particles = false; bool show_emitter = false; bool hide_emitter = false; bool hide_as_dupli_parent = false; @@ -460,20 +498,17 @@ static bool object_render_hide(BL::Object& b_ob, if((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) && (b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) hair_present = true; - - if(b_psys->settings().use_render_emitter()) - show_emitter = true; - else - hide_emitter = true; + has_particles = true; } - if(show_emitter) - hide_emitter = false; - - /* duplicators hidden by default, except dupliframes which duplicate self */ - if(b_ob.is_duplicator()) - if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES) + if(has_particles) { + show_emitter = b_ob.show_duplicator_for_render(); + hide_emitter = !show_emitter; + } else if(b_ob.is_duplicator()) { + if(top_level || b_ob.show_duplicator_for_render()) { hide_as_dupli_parent = true; + } + } /* hide original object for duplis */ BL::Object parent = b_ob.parent(); @@ -502,19 +537,11 @@ static bool object_render_hide(BL::Object& b_ob, } } -static bool object_render_hide_duplis(BL::Object& b_ob) -{ - BL::Object parent = b_ob.parent(); - - return (parent && object_render_hide_original(b_ob.type(), parent.dupli_type())); -} - /* Object Loop */ -void BlenderSync::sync_objects(float motion_time) +void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time) { /* layer data */ - uint scene_layer = render_layer.scene_layer; bool motion = motion_time != 0.0f; if(!motion) { @@ -533,100 +560,39 @@ void BlenderSync::sync_objects(float motion_time) BlenderObjectCulling culling(scene, b_scene); /* object loop */ - BL::Scene::object_bases_iterator b_base; - BL::Scene b_sce = b_scene; - /* modifier result type (not exposed as enum in C++ API) - * 1 : DAG_EVAL_PREVIEW - * 2 : DAG_EVAL_RENDER - */ - int dupli_settings = (render_layer.use_viewport_visibility) ? 1 : 2; - bool cancel = false; bool use_portal = false; - uint layer_override = get_layer(b_engine.layer_override()); - for(; b_sce && !cancel; b_sce = b_sce.background_set()) { - /* Render layer's scene_layer is affected by local view already, - * which is not a desired behavior here. - */ - uint scene_layers = layer_override ? layer_override : get_layer(b_scene.layers()); - for(b_sce.object_bases.begin(b_base); b_base != b_sce.object_bases.end() && !cancel; ++b_base) { - BL::Object b_ob = b_base->object(); - bool hide = (render_layer.use_viewport_visibility)? b_ob.hide(): b_ob.hide_render(); - uint ob_layer = get_layer(b_base->layers(), - b_base->layers_local_view(), - object_is_light(b_ob), - scene_layers); - hide = hide || !(ob_layer & scene_layer); - - if(!hide) { - progress.set_sync_status("Synchronizing object", b_ob.name()); - - /* load per-object culling data */ - culling.init_object(scene, b_ob); - - if(b_ob.is_duplicator() && !object_render_hide_duplis(b_ob)) { - /* dupli objects */ - b_ob.dupli_list_create(b_scene, dupli_settings); - - BL::Object::dupli_list_iterator b_dup; - - for(b_ob.dupli_list.begin(b_dup); b_dup != b_ob.dupli_list.end(); ++b_dup) { - Transform tfm = get_transform(b_dup->matrix()); - BL::Object b_dup_ob = b_dup->object(); - bool dup_hide = (render_layer.use_viewport_visibility)? b_dup_ob.hide(): b_dup_ob.hide_render(); - bool in_dupli_group = (b_dup->type() == BL::DupliObject::type_GROUP); - bool hide_tris; - - if(!(b_dup->hide() || dup_hide || object_render_hide(b_dup_ob, false, in_dupli_group, hide_tris))) { - /* the persistent_id allows us to match dupli objects - * between frames and updates */ - BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id(); - - /* sync object and mesh or light data */ - Object *object = sync_object(b_ob, - persistent_id.data, - *b_dup, - tfm, - ob_layer, - motion_time, - hide_tris, - culling, - &use_portal); - - /* sync possible particle data, note particle_id - * starts counting at 1, first is dummy particle */ - if(!motion && object) { - sync_dupli_particle(b_ob, *b_dup, object); - } - - } - } - - b_ob.dupli_list_clear(); - } + BL::Depsgraph::duplis_iterator b_dupli_iter; + for(b_depsgraph.duplis.begin(b_dupli_iter); + b_dupli_iter != b_depsgraph.duplis.end() && !cancel; + ++b_dupli_iter) + { + BL::Object b_ob = b_dupli_iter->object(); + if(!b_ob.is_visible()) { + continue; + } - /* test if object needs to be hidden */ - bool hide_tris; - - if(!object_render_hide(b_ob, true, true, hide_tris)) { - /* object itself */ - Transform tfm = get_transform(b_ob.matrix_world()); - BL::DupliObject b_empty_dupli_ob(PointerRNA_NULL); - sync_object(b_ob, - NULL, - b_empty_dupli_ob, - tfm, - ob_layer, - motion_time, - hide_tris, - culling, - &use_portal); - } - } + progress.set_sync_status("Synchronizing object", b_ob.name()); - cancel = progress.get_cancel(); - } + /* load per-object culling data */ + culling.init_object(scene, b_ob); + + /* test if object needs to be hidden */ + bool hide_tris; + + if(!object_render_hide(b_ob, true, true, hide_tris)) { + /* object itself */ + sync_object(b_depsgraph, + b_dupli_iter, + ~(0), /* until we get rid of layers */ + motion_time, + hide_tris, + culling, + &use_portal); + } + + cancel = progress.get_cancel(); } progress.set_sync_status(""); @@ -650,6 +616,7 @@ void BlenderSync::sync_objects(float motion_time) } void BlenderSync::sync_motion(BL::RenderSettings& b_render, + BL::Depsgraph& b_depsgraph, BL::Object& b_override, int width, int height, void **python_thread_state) @@ -679,6 +646,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render, assert(scene->camera->motion_position == Camera::MOTION_POSITION_START); frame_center_delta = shuttertime * 0.5f; } + float time = frame_center + subframe_center + frame_center_delta; int frame = (int)floorf(time); float subframe = time - frame; @@ -686,7 +654,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render, b_engine.frame_set(frame, subframe); python_thread_state_save(python_thread_state); sync_camera_motion(b_render, b_cam, width, height, 0.0f); - sync_objects(0.0f); + sync_objects(b_depsgraph, 0.0f); } /* always sample these times for camera motion */ @@ -725,7 +693,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render, } /* sync object */ - sync_objects(relative_time); + sync_objects(b_depsgraph, relative_time); } /* we need to set the python thread state again because this diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index 00f8cb3cf1b..e365061722e 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -28,7 +28,7 @@ CCL_NAMESPACE_BEGIN /* Utilities */ bool BlenderSync::sync_dupli_particle(BL::Object& b_ob, - BL::DupliObject& b_dup, + BL::DepsgraphIter& b_dup, Object *object) { /* test if this dupli was generated from a particle sytem */ diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 76cc18dd9a1..84b90cb53de 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -203,10 +203,10 @@ static PyObject *exit_func(PyObject * /*self*/, PyObject * /*args*/) static PyObject *create_func(PyObject * /*self*/, PyObject *args) { - PyObject *pyengine, *pyuserpref, *pydata, *pyscene, *pyregion, *pyv3d, *pyrv3d; + PyObject *pyengine, *pyuserpref, *pydata, *pyregion, *pyv3d, *pyrv3d; int preview_osl; - if(!PyArg_ParseTuple(args, "OOOOOOOi", &pyengine, &pyuserpref, &pydata, &pyscene, + if(!PyArg_ParseTuple(args, "OOOOOOi", &pyengine, &pyuserpref, &pydata, &pyregion, &pyv3d, &pyrv3d, &preview_osl)) { return NULL; @@ -225,10 +225,6 @@ static PyObject *create_func(PyObject * /*self*/, PyObject *args) RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr); BL::BlendData data(dataptr); - PointerRNA sceneptr; - RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr); - BL::Scene scene(sceneptr); - PointerRNA regionptr; RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), ®ionptr); BL::Region region(regionptr); @@ -249,27 +245,13 @@ static PyObject *create_func(PyObject * /*self*/, PyObject *args) int width = region.width(); int height = region.height(); - session = new BlenderSession(engine, userpref, data, scene, v3d, rv3d, width, height); + session = new BlenderSession(engine, userpref, data, v3d, rv3d, width, height); } else { - /* override some settings for preview */ - if(engine.is_preview()) { - PointerRNA cscene = RNA_pointer_get(&sceneptr, "cycles"); - - RNA_boolean_set(&cscene, "shading_system", preview_osl); - RNA_boolean_set(&cscene, "use_progressive_refine", true); - } - /* offline session or preview render */ - session = new BlenderSession(engine, userpref, data, scene); + session = new BlenderSession(engine, userpref, data, preview_osl); } - python_thread_state_save(&session->python_thread_state); - - session->create(); - - python_thread_state_restore(&session->python_thread_state); - return PyLong_FromVoidPtr(session); } @@ -280,13 +262,22 @@ static PyObject *free_func(PyObject * /*self*/, PyObject *value) Py_RETURN_NONE; } -static PyObject *render_func(PyObject * /*self*/, PyObject *value) +static PyObject *render_func(PyObject * /*self*/, PyObject *args) { - BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value); + PyObject *pysession, *pydepsgraph; + + if(!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph)) + return NULL; + + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + + PointerRNA depsgraphptr; + RNA_pointer_create(NULL, &RNA_Depsgraph, (ID*)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr); + BL::Depsgraph b_depsgraph(depsgraphptr); python_thread_state_save(&session->python_thread_state); - session->render(); + session->render(b_depsgraph); python_thread_state_restore(&session->python_thread_state); @@ -296,16 +287,20 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *value) /* pixel_array and result passed as pointers */ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) { - PyObject *pysession, *pyobject; + PyObject *pysession, *pydepsgraph, *pyobject; PyObject *pypixel_array, *pyresult; const char *pass_type; int num_pixels, depth, object_id, pass_filter; - if(!PyArg_ParseTuple(args, "OOsiiOiiO", &pysession, &pyobject, &pass_type, &pass_filter, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult)) + if(!PyArg_ParseTuple(args, "OOOsiiOiiO", &pysession, &pydepsgraph, &pyobject, &pass_type, &pass_filter, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult)) return NULL; BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + PointerRNA depsgraphptr; + RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr); + BL::Depsgraph b_depsgraph(depsgraphptr); + PointerRNA objectptr; RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyobject), &objectptr); BL::Object b_object(objectptr); @@ -318,7 +313,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) python_thread_state_save(&session->python_thread_state); - session->bake(b_object, pass_type, pass_filter, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); + session->bake(b_depsgraph, b_object, pass_type, pass_filter, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); python_thread_state_restore(&session->python_thread_state); @@ -327,9 +322,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) static PyObject *draw_func(PyObject * /*self*/, PyObject *args) { - PyObject *pysession, *pyv3d, *pyrv3d; + PyObject *pysession, *pygraph, *pyv3d, *pyrv3d; - if(!PyArg_ParseTuple(args, "OOO", &pysession, &pyv3d, &pyrv3d)) + if(!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d)) return NULL; BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); @@ -347,9 +342,9 @@ static PyObject *draw_func(PyObject * /*self*/, PyObject *args) static PyObject *reset_func(PyObject * /*self*/, PyObject *args) { - PyObject *pysession, *pydata, *pyscene; + PyObject *pysession, *pydata, *pydepsgraph; - if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene)) + if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph)) return NULL; BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); @@ -358,26 +353,35 @@ static PyObject *reset_func(PyObject * /*self*/, PyObject *args) RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr); BL::BlendData b_data(dataptr); - PointerRNA sceneptr; - RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr); - BL::Scene b_scene(sceneptr); + PointerRNA depsgraphptr; + RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr); + BL::Depsgraph b_depsgraph(depsgraphptr); python_thread_state_save(&session->python_thread_state); - session->reset_session(b_data, b_scene); + session->reset_session(b_data, b_depsgraph); python_thread_state_restore(&session->python_thread_state); Py_RETURN_NONE; } -static PyObject *sync_func(PyObject * /*self*/, PyObject *value) +static PyObject *sync_func(PyObject * /*self*/, PyObject *args) { - BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value); + PyObject *pysession, *pydepsgraph; + + if(!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph)) + return NULL; + + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + + PointerRNA depsgraphptr; + RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr); + BL::Depsgraph b_depsgraph(depsgraphptr); python_thread_state_save(&session->python_thread_state); - session->synchronize(); + session->synchronize(b_depsgraph); python_thread_state_restore(&session->python_thread_state); @@ -753,10 +757,10 @@ static PyMethodDef methods[] = { {"exit", exit_func, METH_VARARGS, ""}, {"create", create_func, METH_VARARGS, ""}, {"free", free_func, METH_O, ""}, - {"render", render_func, METH_O, ""}, + {"render", render_func, METH_VARARGS, ""}, {"bake", bake_func, METH_VARARGS, ""}, {"draw", draw_func, METH_VARARGS, ""}, - {"sync", sync_func, METH_O, ""}, + {"sync", sync_func, METH_VARARGS, ""}, {"reset", reset_func, METH_VARARGS, ""}, #ifdef WITH_OSL {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 00d23b9095e..bfaa843eb18 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -52,21 +52,22 @@ int BlenderSession::end_resumable_chunk = 0; BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, BL::BlendData& b_data, - BL::Scene& b_scene) -: b_engine(b_engine), + bool preview_osl) +: session(NULL), + b_engine(b_engine), b_userpref(b_userpref), b_data(b_data), b_render(b_engine.render()), - b_scene(b_scene), + b_depsgraph(PointerRNA_NULL), + b_scene(PointerRNA_NULL), b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL), + width(0), + height(0), + preview_osl(preview_osl), python_thread_state(NULL) { /* offline render */ - - width = render_resolution_x(b_render); - height = render_resolution_y(b_render); - background = true; last_redraw_time = 0.0; start_resize_time = 0.0; @@ -76,23 +77,24 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, BL::BlendData& b_data, - BL::Scene& b_scene, BL::SpaceView3D& b_v3d, BL::RegionView3D& b_rv3d, int width, int height) -: b_engine(b_engine), +: session(NULL), + b_engine(b_engine), b_userpref(b_userpref), b_data(b_data), - b_render(b_scene.render()), - b_scene(b_scene), + b_render(b_engine.render()), + b_depsgraph(PointerRNA_NULL), + b_scene(PointerRNA_NULL), b_v3d(b_v3d), b_rv3d(b_rv3d), width(width), height(height), + preview_osl(false), python_thread_state(NULL) { /* 3d view render */ - background = false; last_redraw_time = 0.0; start_resize_time = 0.0; @@ -141,26 +143,19 @@ void BlenderSession::create_session() session->scene = scene; + /* There is no single depsgraph to use for the entire render. + * So we need to handle this differently. + * + * We could loop over the final render result render layers in pipeline and keep Cycles unaware of multiple layers, + * or perhaps move syncing further down in the pipeline. + */ /* create sync */ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); BL::Object b_camera_override(b_engine.camera_override()); if(b_v3d) { - if(session_pause == false) { - /* full data sync */ - sync->sync_view(b_v3d, b_rv3d, width, height); - sync->sync_data(b_render, - b_v3d, - b_camera_override, - width, height, - &python_thread_state, - b_rlay_name.c_str()); - } + sync->sync_view(b_v3d, b_rv3d, width, height); } else { - /* for final render we will do full data sync per render layer, only - * do some basic syncing here, no objects or materials for speed */ - sync->sync_render_layers(b_v3d, NULL); - sync->sync_integrator(); sync->sync_camera(b_render, b_camera_override, width, height, ""); } @@ -173,18 +168,40 @@ void BlenderSession::create_session() update_resumable_tile_manager(session_params.samples); } -void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_) +void BlenderSession::reset_session(BL::BlendData& b_data, BL::Depsgraph& b_depsgraph) { - b_data = b_data_; - b_render = b_engine.render(); - b_scene = b_scene_; + this->b_data = b_data; + this->b_depsgraph = b_depsgraph; + this->b_scene = b_depsgraph.scene_eval(); + + if (preview_osl) { + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + RNA_boolean_set(&cscene, "shading_system", preview_osl); + } + + if (b_v3d) { + this->b_render = b_scene.render(); + } + else { + this->b_render = b_engine.render(); + width = render_resolution_x(b_render); + height = render_resolution_y(b_render); + } + + if (session == NULL) { + create(); + } + + if (b_v3d) { + /* NOTE: We need to create session, but all the code from below + * will make viewport render to stuck on initialization. + */ + return; + } SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); - width = render_resolution_x(b_render); - height = render_resolution_y(b_render); - if(scene->params.modified(scene_params) || session->params.modified(session_params) || !scene_params.persistent_data) @@ -210,16 +227,12 @@ void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_) */ session->stats.mem_peak = session->stats.mem_used; + /* There is no single depsgraph to use for the entire render. + * See note on create_session(). + */ /* sync object should be re-created */ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); - /* for final render we will do full data sync per render layer, only - * do some basic syncing here, no objects or materials for speed */ - BL::Object b_camera_override(b_engine.camera_override()); - sync->sync_render_layers(b_v3d, NULL); - sync->sync_integrator(); - sync->sync_camera(b_render, b_camera_override, width, height, ""); - BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL); BL::RegionView3D b_null_region_view3d(PointerRNA_NULL); BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, @@ -368,8 +381,10 @@ void BlenderSession::update_render_tile(RenderTile& rtile, bool highlight) do_write_update_render_tile(rtile, false, false); } -void BlenderSession::render() +void BlenderSession::render(BL::Depsgraph& b_depsgraph_) { + b_depsgraph = b_depsgraph_; + /* set callback to write out render results */ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1, _2); @@ -379,123 +394,109 @@ void BlenderSession::render() BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ - BL::RenderSettings r = b_scene.render(); - BL::RenderSettings::layers_iterator b_layer_iter; - BL::RenderResult::views_iterator b_view_iter; + BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); /* We do some special meta attributes when we only have single layer. */ - const bool is_single_layer = (r.layers.length() == 1); - - for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) { - b_rlay_name = b_layer_iter->name(); + const bool is_single_layer = (b_scene.view_layers.length() == 1); - /* temporary render result to find needed passes and views */ - BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL); - BL::RenderResult::layers_iterator b_single_rlay; - b_rr.layers.begin(b_single_rlay); + /* temporary render result to find needed passes and views */ + BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL); + BL::RenderResult::layers_iterator b_single_rlay; + b_rr.layers.begin(b_single_rlay); + BL::RenderLayer b_rlay = *b_single_rlay; - /* layer will be missing if it was disabled in the UI */ - if(b_single_rlay == b_rr.layers.end()) { - end_render_result(b_engine, b_rr, true, true, false); - continue; - } + /* add passes */ + array<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer, session_params); + buffer_params.passes = passes; + + PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles"); + bool use_denoising = get_boolean(crl, "use_denoising"); + buffer_params.denoising_data_pass = use_denoising; + session->tile_manager.schedule_denoising = use_denoising; + session->params.use_denoising = use_denoising; + scene->film->denoising_data_pass = buffer_params.denoising_data_pass; + scene->film->denoising_flags = 0; + if(!get_boolean(crl, "denoising_diffuse_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_DIR; + if(!get_boolean(crl, "denoising_diffuse_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_IND; + if(!get_boolean(crl, "denoising_glossy_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_DIR; + if(!get_boolean(crl, "denoising_glossy_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_IND; + if(!get_boolean(crl, "denoising_transmission_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_DIR; + if(!get_boolean(crl, "denoising_transmission_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_IND; + if(!get_boolean(crl, "denoising_subsurface_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_DIR; + if(!get_boolean(crl, "denoising_subsurface_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_IND; + scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); + buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass; + session->params.denoising_radius = get_int(crl, "denoising_radius"); + session->params.denoising_strength = get_float(crl, "denoising_strength"); + session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength"); + session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca"); + + scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold(); + scene->film->tag_passes_update(scene, passes); + scene->film->tag_update(scene); + scene->integrator->tag_update(scene); - BL::RenderLayer b_rlay = *b_single_rlay; - - /* add passes */ - array<Pass> passes = sync->sync_render_passes(b_rlay, *b_layer_iter, session_params); - buffer_params.passes = passes; - - PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles"); - bool use_denoising = get_boolean(crl, "use_denoising"); - buffer_params.denoising_data_pass = use_denoising; - session->tile_manager.schedule_denoising = use_denoising; - session->params.use_denoising = use_denoising; - scene->film->denoising_data_pass = buffer_params.denoising_data_pass; - scene->film->denoising_flags = 0; - if(!get_boolean(crl, "denoising_diffuse_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_DIR; - if(!get_boolean(crl, "denoising_diffuse_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_IND; - if(!get_boolean(crl, "denoising_glossy_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_DIR; - if(!get_boolean(crl, "denoising_glossy_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_GLOSSY_IND; - if(!get_boolean(crl, "denoising_transmission_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_DIR; - if(!get_boolean(crl, "denoising_transmission_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_TRANSMISSION_IND; - if(!get_boolean(crl, "denoising_subsurface_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_DIR; - if(!get_boolean(crl, "denoising_subsurface_indirect")) scene->film->denoising_flags |= DENOISING_CLEAN_SUBSURFACE_IND; - scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES); - buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass; - session->params.denoising_radius = get_int(crl, "denoising_radius"); - session->params.denoising_strength = get_float(crl, "denoising_strength"); - session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength"); - session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca"); - - scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold(); - scene->film->tag_passes_update(scene, passes); - scene->film->tag_update(scene); - scene->integrator->tag_update(scene); - - int view_index = 0; - for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) { - b_rview_name = b_view_iter->name(); - - /* set the current view */ - b_engine.active_view_set(b_rview_name.c_str()); - - /* update scene */ - BL::Object b_camera_override(b_engine.camera_override()); - sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str()); - sync->sync_data(b_render, - b_v3d, - b_camera_override, - width, height, - &python_thread_state, - b_rlay_name.c_str()); - - /* Make sure all views have different noise patterns. - hardcoded value just to make it random */ - if(view_index != 0) { - scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef)); - scene->integrator->tag_update(scene); - } + BL::RenderResult::views_iterator b_view_iter; + int view_index = 0; + for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) { + b_rlay_name = b_view_layer.name(); + b_rview_name = b_view_iter->name(); - /* Update number of samples per layer. */ - int samples = sync->get_layer_samples(); - bool bound_samples = sync->get_layer_bound_samples(); - int effective_layer_samples; + /* set the current view */ + b_engine.active_view_set(b_rview_name.c_str()); - if(samples != 0 && (!bound_samples || (samples < session_params.samples))) - effective_layer_samples = samples; - else - effective_layer_samples = session_params.samples; + /* update scene */ + BL::Object b_camera_override(b_engine.camera_override()); + sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str()); + sync->sync_data(b_render, + b_depsgraph, + b_v3d, + b_camera_override, + width, height, + &python_thread_state); - /* Update tile manager if we're doing resumable render. */ - update_resumable_tile_manager(effective_layer_samples); + /* Make sure all views have different noise patterns. - hardcoded value just to make it random */ + if(view_index != 0) { + scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef)); + scene->integrator->tag_update(scene); + } - /* Update session itself. */ - session->reset(buffer_params, effective_layer_samples); + /* Update number of samples per layer. */ + int samples = sync->get_layer_samples(); + bool bound_samples = sync->get_layer_bound_samples(); + int effective_layer_samples; - /* render */ - session->start(); - session->wait(); + if(samples != 0 && (!bound_samples || (samples < session_params.samples))) + effective_layer_samples = samples; + else + effective_layer_samples = session_params.samples; - if(session->progress.get_cancel()) - break; - } + /* Update tile manager if we're doing resumable render. */ + update_resumable_tile_manager(effective_layer_samples); - if(is_single_layer) { - BL::RenderResult b_rr = b_engine.get_result(); - string num_aa_samples = string_printf("%d", session->params.samples); - b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str()); - /* TODO(sergey): Report whether we're doing resumable render - * and also start/end sample if so. - */ - } + /* Update session itself. */ + session->reset(buffer_params, effective_layer_samples); - /* free result without merging */ - end_render_result(b_engine, b_rr, true, true, false); + /* render */ + session->start(); + session->wait(); if(session->progress.get_cancel()) break; } + if(is_single_layer) { + BL::RenderResult b_rr = b_engine.get_result(); + string num_aa_samples = string_printf("%d", session->params.samples); + b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str()); + /* TODO(sergey): Report whether we're doing resumable render + * and also start/end sample if so. + */ + } + + /* free result without merging */ + end_render_result(b_engine, b_rr, true, true, false); + double total_time, render_time; session->progress.get_time(total_time, render_time); VLOG(1) << "Total render time: " << total_time; @@ -505,6 +506,8 @@ void BlenderSession::render() session->write_render_tile_cb = function_null; session->update_render_tile_cb = function_null; + /* TODO: find a way to clear this data for persistent data render */ +#if 0 /* free all memory used (host and device), so we wouldn't leave render * engine with extra memory allocated */ @@ -513,6 +516,7 @@ void BlenderSession::render() delete sync; sync = NULL; +#endif } static void populate_bake_data(BakeData *data, const @@ -561,7 +565,8 @@ static int bake_pass_filter_get(const int pass_filter) return flag; } -void BlenderSession::bake(BL::Object& b_object, +void BlenderSession::bake(BL::Depsgraph& b_depsgraph_, + BL::Object& b_object, const string& pass_type, const int pass_filter, const int object_id, @@ -570,6 +575,8 @@ void BlenderSession::bake(BL::Object& b_object, const int /*depth*/, float result[]) { + b_depsgraph = b_depsgraph_; + ShaderEvalType shader_type = get_shader_type(pass_type); /* Set baking flag in advance, so kernel loading can check if we need @@ -602,11 +609,11 @@ void BlenderSession::bake(BL::Object& b_object, BL::Object b_camera_override(b_engine.camera_override()); sync->sync_camera(b_render, b_camera_override, width, height, ""); sync->sync_data(b_render, + b_depsgraph, b_v3d, b_camera_override, width, height, - &python_thread_state, - b_rlay_name.c_str()); + &python_thread_state); } BakeData *bake_data = NULL; @@ -740,7 +747,7 @@ void BlenderSession::update_render_result(BL::RenderResult& b_rr, do_write_update_render_result(b_rr, b_rlay, rtile, true); } -void BlenderSession::synchronize() +void BlenderSession::synchronize(BL::Depsgraph& b_depsgraph_) { /* only used for viewport render */ if(!b_v3d) @@ -781,13 +788,15 @@ void BlenderSession::synchronize() } /* data and camera synchronize */ + b_depsgraph = b_depsgraph_; + BL::Object b_camera_override(b_engine.camera_override()); sync->sync_data(b_render, + b_depsgraph, b_v3d, b_camera_override, width, height, - &python_thread_state, - b_rlay_name.c_str()); + &python_thread_state); if(b_rv3d) sync->sync_view(b_v3d, b_rv3d, width, height); @@ -1301,6 +1310,9 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); } else { + /* We originally were passing view_layer here but in reality we need a + * a depsgraph to pass to the RE_point_density_minmax() function. + */ /* TODO(sergey): Check we're indeed in shader node tree. */ PointerRNA ptr; RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); @@ -1308,8 +1320,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { BL::ShaderNodeTexPointDensity b_point_density_node(b_node); int length; - int settings = background ? 1 : 0; /* 1 - render settings, 0 - vewport settings. */ - b_point_density_node.calc_point_density(b_scene, settings, &length, &pixels); + b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels); } } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 3804e07cffc..aecb304c270 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -37,12 +37,11 @@ public: BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, BL::BlendData& b_data, - BL::Scene& b_scene); + bool preview_osl); BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, BL::BlendData& b_data, - BL::Scene& b_scene, BL::SpaceView3D& b_v3d, BL::RegionView3D& b_rv3d, int width, int height); @@ -56,12 +55,13 @@ public: void free_session(); void reset_session(BL::BlendData& b_data, - BL::Scene& b_scene); + BL::Depsgraph& b_depsgraph); /* offline render */ - void render(); + void render(BL::Depsgraph& b_depsgraph); - void bake(BL::Object& b_object, + void bake(BL::Depsgraph& b_depsgrah, + BL::Object& b_object, const string& pass_type, const int custom_flag, const int object_id, @@ -83,7 +83,7 @@ public: void update_render_tile(RenderTile& rtile, bool highlight); /* interactive updates */ - void synchronize(); + void synchronize(BL::Depsgraph& b_depsgraph); /* drawing */ bool draw(int w, int h); @@ -105,6 +105,7 @@ public: BL::UserPreferences b_userpref; BL::BlendData b_data; BL::RenderSettings b_render; + BL::Depsgraph b_depsgraph; BL::Scene b_scene; BL::SpaceView3D b_v3d; BL::RegionView3D b_rv3d; @@ -117,6 +118,7 @@ public: double last_status_time; int width, height; + bool preview_osl; double start_resize_time; void *python_thread_state; diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 9896dd1d94f..8847d651b02 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -231,18 +231,11 @@ static void get_tex_mapping(TextureMapping *mapping, mapping->max = get_float3(b_mapping.max()); } -static bool is_output_node(BL::Node& b_node) -{ - return (b_node.is_a(&RNA_ShaderNodeOutputMaterial) - || b_node.is_a(&RNA_ShaderNodeOutputWorld) - || b_node.is_a(&RNA_ShaderNodeOutputLamp)); -} - static ShaderNode *add_node(Scene *scene, BL::RenderEngine& b_engine, BL::BlendData& b_data, + BL::Depsgraph& b_depsgraph, BL::Scene& b_scene, - const bool background, ShaderGraph *graph, BL::ShaderNodeTree& b_ntree, BL::ShaderNode& b_node) @@ -864,12 +857,9 @@ static ShaderNode *add_node(Scene *scene, point_density->interpolation = get_image_interpolation(b_point_density_node); point_density->builtin_data = b_point_density_node.ptr.data; - /* 1 - render settings, 0 - vewport settings. */ - int settings = background ? 1 : 0; - /* TODO(sergey): Use more proper update flag. */ if(true) { - b_point_density_node.cache_point_density(b_scene, settings); + b_point_density_node.cache_point_density(b_depsgraph); scene->image_manager->tag_reload_image( point_density->filename.string(), point_density->builtin_data, @@ -887,9 +877,8 @@ static ShaderNode *add_node(Scene *scene, BL::Object b_ob(b_point_density_node.object()); if(b_ob) { float3 loc, size; - point_density_texture_space(b_scene, + point_density_texture_space(b_depsgraph, b_point_density_node, - settings, loc, size); point_density->tfm = @@ -999,11 +988,36 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, return node->output(name.c_str()); } +static BL::ShaderNode find_output_node(BL::ShaderNodeTree& b_ntree) +{ + BL::ShaderNodeTree::nodes_iterator b_node; + BL::ShaderNode output_node(PointerRNA_NULL); + + for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { + BL::ShaderNodeOutputMaterial b_output_node(*b_node); + + if (b_output_node.is_a(&RNA_ShaderNodeOutputMaterial) || + b_output_node.is_a(&RNA_ShaderNodeOutputWorld) || + b_output_node.is_a(&RNA_ShaderNodeOutputLamp)) { + /* regular Cycles output node */ + if(b_output_node.is_active_output()) { + output_node = b_output_node; + break; + } + else if(!output_node.ptr.data) { + output_node = b_output_node; + } + } + } + + return output_node; +} + static void add_nodes(Scene *scene, BL::RenderEngine& b_engine, BL::BlendData& b_data, + BL::Depsgraph& b_depsgraph, BL::Scene& b_scene, - const bool background, ShaderGraph *graph, BL::ShaderNodeTree& b_ntree, const ProxyMap &proxy_input_map, @@ -1018,23 +1032,7 @@ static void add_nodes(Scene *scene, BL::Node::outputs_iterator b_output; /* find the node to use for output if there are multiple */ - bool found_active_output = false; - BL::ShaderNode output_node(PointerRNA_NULL); - - for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if(is_output_node(*b_node)) { - BL::ShaderNodeOutputMaterial b_output_node(*b_node); - - if(b_output_node.is_active_output()) { - output_node = b_output_node; - found_active_output = true; - break; - } - else if(!output_node.ptr.data && !found_active_output) { - output_node = b_output_node; - } - } - } + BL::ShaderNode output_node = find_output_node(b_ntree); /* add nodes */ for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { @@ -1104,8 +1102,8 @@ static void add_nodes(Scene *scene, add_nodes(scene, b_engine, b_data, + b_depsgraph, b_scene, - background, graph, b_group_ntree, group_proxy_input_map, @@ -1143,18 +1141,16 @@ static void add_nodes(Scene *scene, else { ShaderNode *node = NULL; - if(is_output_node(*b_node)) { - if(b_node->ptr.data == output_node.ptr.data) { - node = graph->output(); - } + if(b_node->ptr.data == output_node.ptr.data) { + node = graph->output(); } else { BL::ShaderNode b_shader_node(*b_node); node = add_node(scene, b_engine, b_data, + b_depsgraph, b_scene, - background, graph, b_ntree, b_shader_node); @@ -1216,8 +1212,8 @@ static void add_nodes(Scene *scene, static void add_nodes(Scene *scene, BL::RenderEngine& b_engine, BL::BlendData& b_data, + BL::Depsgraph& b_depsgraph, BL::Scene& b_scene, - const bool background, ShaderGraph *graph, BL::ShaderNodeTree& b_ntree) { @@ -1225,8 +1221,8 @@ static void add_nodes(Scene *scene, add_nodes(scene, b_engine, b_data, + b_depsgraph, b_scene, - background, graph, b_ntree, empty_proxy_map, @@ -1235,17 +1231,22 @@ static void add_nodes(Scene *scene, /* Sync Materials */ -void BlenderSync::sync_materials(bool update_all) +void BlenderSync::sync_materials(BL::Depsgraph& b_depsgraph, bool update_all) { shader_map.set_default(scene->default_surface); - /* material loop */ - BL::BlendData::materials_iterator b_mat; - TaskPool pool; set<Shader*> updated_shaders; - for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { + /* material loop */ + BL::BlendData::materials_iterator b_mat_orig; + for(b_data.materials.begin(b_mat_orig); + b_mat_orig != b_data.materials.end(); + ++b_mat_orig) + { + /* TODO(sergey): Iterate over evaluated data rather than using mapping. */ + BL::Material b_mat_(b_depsgraph.id_eval_get(*b_mat_orig)); + BL::Material *b_mat = &b_mat_; Shader *shader; /* test if we need to sync */ @@ -1259,7 +1260,7 @@ void BlenderSync::sync_materials(bool update_all) if(b_mat->use_nodes() && b_mat->node_tree()) { BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree); + add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree); } else { DiffuseBsdfNode *diffuse = new DiffuseBsdfNode(); @@ -1315,7 +1316,7 @@ void BlenderSync::sync_materials(bool update_all) /* Sync World */ -void BlenderSync::sync_world(bool update_all) +void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all) { Background *background = scene->background; Background prevbackground = *background; @@ -1330,7 +1331,7 @@ void BlenderSync::sync_world(bool update_all) if(b_world && b_world.use_nodes() && b_world.node_tree()) { BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree); + add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree); /* volume */ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); @@ -1398,8 +1399,8 @@ void BlenderSync::sync_world(bool update_all) background->transparent_roughness_threshold = 0.0f; } - background->use_shader = render_layer.use_background_shader; - background->use_ao = background->use_ao && render_layer.use_background_ao; + background->use_shader = view_layer.use_background_shader; + background->use_ao = background->use_ao && view_layer.use_background_ao; if(background->modified(prevbackground)) background->tag_update(scene); @@ -1407,14 +1408,19 @@ void BlenderSync::sync_world(bool update_all) /* Sync Lamps */ -void BlenderSync::sync_lamps(bool update_all) +void BlenderSync::sync_lamps(BL::Depsgraph& b_depsgraph, bool update_all) { shader_map.set_default(scene->default_light); /* lamp loop */ - BL::BlendData::lamps_iterator b_lamp; - - for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) { + BL::BlendData::lamps_iterator b_lamp_orig; + for(b_data.lamps.begin(b_lamp_orig); + b_lamp_orig != b_data.lamps.end(); + ++b_lamp_orig) + { + /* TODO(sergey): Iterate over evaluated data rather than using mapping. */ + BL::Lamp b_lamp_(b_depsgraph.id_eval_get(*b_lamp_orig)); + BL::Lamp *b_lamp = &b_lamp_; Shader *shader; /* test if we need to sync */ @@ -1427,7 +1433,7 @@ void BlenderSync::sync_lamps(bool update_all) BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree); + add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree); } else { float strength = 1.0f; @@ -1454,7 +1460,7 @@ void BlenderSync::sync_lamps(bool update_all) } } -void BlenderSync::sync_shaders() +void BlenderSync::sync_shaders(BL::Depsgraph& b_depsgraph) { /* for auto refresh images */ bool auto_refresh_update = false; @@ -1467,9 +1473,9 @@ void BlenderSync::sync_shaders() shader_map.pre_sync(); - sync_world(auto_refresh_update); - sync_lamps(auto_refresh_update); - sync_materials(auto_refresh_update); + sync_world(b_depsgraph, auto_refresh_update); + sync_lamps(b_depsgraph, auto_refresh_update); + sync_materials(b_depsgraph, auto_refresh_update); /* false = don't delete unused shaders, not supported */ shader_map.post_sync(false); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 283aa5600fd..c175ed252f7 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -189,16 +189,18 @@ bool BlenderSync::sync_recalc() } void BlenderSync::sync_data(BL::RenderSettings& b_render, + BL::Depsgraph& b_depsgraph, BL::SpaceView3D& b_v3d, BL::Object& b_override, int width, int height, - void **python_thread_state, - const char *layer) + void **python_thread_state) { - sync_render_layers(b_v3d, layer); + BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); + + sync_view_layer(b_v3d, b_view_layer); sync_integrator(); sync_film(); - sync_shaders(); + sync_shaders(b_depsgraph); sync_images(); sync_curve_settings(); @@ -208,9 +210,10 @@ void BlenderSync::sync_data(BL::RenderSettings& b_render, scene->need_motion() == Scene::MOTION_NONE || scene->camera->motion_position == Camera::MOTION_POSITION_CENTER) { - sync_objects(); + sync_objects(b_depsgraph); } sync_motion(b_render, + b_depsgraph, b_override, width, height, python_thread_state); @@ -369,75 +372,31 @@ void BlenderSync::sync_film() /* Render Layer */ -void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer) +void BlenderSync::sync_view_layer(BL::SpaceView3D& /*b_v3d*/, BL::ViewLayer& b_view_layer) { - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - string layername; - - /* 3d view */ - if(b_v3d) { - if(RNA_boolean_get(&cscene, "preview_active_layer")) { - BL::RenderLayers layers(b_scene.render().ptr); - layername = layers.active().name(); - layer = layername.c_str(); - } - else { - render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view()); - render_layer.layer = render_layer.scene_layer; - render_layer.exclude_layer = 0; - render_layer.holdout_layer = 0; - render_layer.material_override = PointerRNA_NULL; - render_layer.use_background_shader = true; - render_layer.use_background_ao = true; - render_layer.use_hair = true; - render_layer.use_surfaces = true; - render_layer.use_viewport_visibility = true; - render_layer.samples = 0; - render_layer.bound_samples = false; - return; - } - } - /* render layer */ - BL::RenderSettings r = b_scene.render(); - BL::RenderSettings::layers_iterator b_rlay; - int use_layer_samples = get_enum(cscene, "use_layer_samples"); - bool first_layer = true; uint layer_override = get_layer(b_engine.layer_override()); - uint scene_layers = layer_override ? layer_override : get_layer(b_scene.layers()); - - for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { - if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { - render_layer.name = b_rlay->name(); - - render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); - render_layer.exclude_layer = get_layer(b_rlay->layers_exclude()); - - render_layer.scene_layer = scene_layers & ~render_layer.exclude_layer; - render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer; - - render_layer.layer = get_layer(b_rlay->layers()); - render_layer.layer |= render_layer.holdout_layer; - - render_layer.material_override = b_rlay->material_override(); - render_layer.use_background_shader = b_rlay->use_sky(); - render_layer.use_background_ao = b_rlay->use_ao(); - render_layer.use_surfaces = b_rlay->use_solid(); - render_layer.use_hair = b_rlay->use_strand(); - render_layer.use_viewport_visibility = false; - - render_layer.bound_samples = (use_layer_samples == 1); - if(use_layer_samples != 2) { - int samples = b_rlay->samples(); - if(get_boolean(cscene, "use_square_samples")) - render_layer.samples = samples * samples; - else - render_layer.samples = samples; - } - } + uint view_layers = layer_override ? layer_override : get_layer(b_scene.layers()); - first_layer = false; - } + view_layer.name = b_view_layer.name(); + + view_layer.holdout_layer = 0; + view_layer.exclude_layer = 0; + + view_layer.view_layer = view_layers & ~view_layer.exclude_layer; + view_layer.view_layer |= view_layer.exclude_layer & view_layer.holdout_layer; + + view_layer.layer = (1 << 20) - 1; + view_layer.layer |= view_layer.holdout_layer; + + view_layer.material_override = PointerRNA_NULL; + view_layer.use_background_shader = b_view_layer.use_sky(); + view_layer.use_background_ao = b_view_layer.use_ao(); + view_layer.use_surfaces = b_view_layer.use_solid(); + view_layer.use_hair = b_view_layer.use_strand(); + + view_layer.bound_samples = false; + view_layer.samples = 0; } /* Images */ @@ -547,7 +506,7 @@ int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass) } array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, - BL::SceneRenderLayer& b_srlay, + BL::ViewLayer& b_view_layer, const SessionParams &session_params) { array<Pass> passes; @@ -570,49 +529,49 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, Pass::add(pass_type, passes); } - PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles"); + PointerRNA crp = RNA_pointer_get(&b_view_layer.ptr, "cycles"); if(get_boolean(crp, "denoising_store_passes") && get_boolean(crp, "use_denoising")) { - b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Depth", 1, "Z", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Depth Variance", 1, "Z", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Shadow A", 3, "XYV", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Shadow B", 3, "XYV", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Image", 3, "RGB", b_srlay.name().c_str()); - b_engine.add_pass("Denoising Image Variance", 3, "RGB", b_srlay.name().c_str()); + b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Depth Variance", 1, "Z", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Shadow A", 3, "XYV", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Shadow B", 3, "XYV", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Image", 3, "RGB", b_view_layer.name().c_str()); + b_engine.add_pass("Denoising Image Variance", 3, "RGB", b_view_layer.name().c_str()); } #ifdef __KERNEL_DEBUG__ if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) { - b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_BVH_TRAVERSED_NODES, passes); } if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) { - b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes); } if(get_boolean(crp, "pass_debug_bvh_intersections")) { - b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug BVH Intersections", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_BVH_INTERSECTIONS, passes); } if(get_boolean(crp, "pass_debug_ray_bounces")) { - b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug Ray Bounces", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_RAY_BOUNCES, passes); } #endif if(get_boolean(crp, "pass_debug_render_time")) { - b_engine.add_pass("Debug Render Time", 1, "X", b_srlay.name().c_str()); + b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str()); Pass::add(PASS_RENDER_TIME, passes); } if(get_boolean(crp, "use_pass_volume_direct")) { - b_engine.add_pass("VolumeDir", 3, "RGB", b_srlay.name().c_str()); + b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str()); Pass::add(PASS_VOLUME_DIRECT, passes); } if(get_boolean(crp, "use_pass_volume_indirect")) { - b_engine.add_pass("VolumeInd", 3, "RGB", b_srlay.name().c_str()); + b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str()); Pass::add(PASS_VOLUME_INDIRECT, passes); } @@ -837,13 +796,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.text_timeout = (double)get_float(cscene, "debug_text_timeout"); /* progressive refine */ - params.progressive_refine = get_boolean(cscene, "use_progressive_refine") && + params.progressive_refine = (b_engine.is_preview() || + get_boolean(cscene, "use_progressive_refine")) && !b_r.use_save_buffers(); if(params.progressive_refine) { - BL::RenderSettings::layers_iterator b_rlay; - for(b_r.layers.begin(b_rlay); b_rlay != b_r.layers.end(); ++b_rlay) { - PointerRNA crl = RNA_pointer_get(&b_rlay->ptr, "cycles"); + BL::Scene::view_layers_iterator b_view_layer; + for(b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end(); ++b_view_layer) { + PointerRNA crl = RNA_pointer_get(&b_view_layer->ptr, "cycles"); if(get_boolean(crl, "use_denoising")) { params.progressive_refine = false; } @@ -871,17 +831,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, params.shadingsystem = SHADINGSYSTEM_OSL; /* color managagement */ -#ifdef GLEW_MX - /* When using GLEW MX we need to check whether we've got an OpenGL - * context for current window. This is because command line rendering - * doesn't have OpenGL context actually. - */ - if(glewGetContext() != NULL) -#endif - { - params.display_buffer_linear = GLEW_ARB_half_float_pixel && - b_engine.support_display_space_shader(b_scene); - } + params.display_buffer_linear = GLEW_ARB_half_float_pixel && + b_engine.support_display_space_shader(b_scene); if(b_engine.is_preview()) { /* For preview rendering we're using same timeout as diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 1e7b0b32518..468e287038c 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -43,6 +43,7 @@ class Mesh; class Object; class ParticleSystem; class Scene; +class ViewLayer; class Shader; class ShaderGraph; class ShaderNode; @@ -60,14 +61,14 @@ public: /* sync */ bool sync_recalc(); void sync_data(BL::RenderSettings& b_render, + BL::Depsgraph& b_depsgraph, BL::SpaceView3D& b_v3d, BL::Object& b_override, int width, int height, - void **python_thread_state, - const char *layer = 0); - void sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer); - array<Pass> sync_render_passes(BL::RenderLayer& b_rlay, - BL::SceneRenderLayer& b_srlay, + void **python_thread_state); + void sync_view_layer(BL::SpaceView3D& b_v3d, BL::ViewLayer& b_view_layer); + array<Pass> sync_render_passes(BL::RenderLayer& b_render_layer, + BL::ViewLayer& b_view_layer, const SessionParams &session_params); void sync_integrator(); void sync_camera(BL::RenderSettings& b_render, @@ -77,8 +78,8 @@ public: void sync_view(BL::SpaceView3D& b_v3d, BL::RegionView3D& b_rv3d, int width, int height); - inline int get_layer_samples() { return render_layer.samples; } - inline int get_layer_bound_samples() { return render_layer.bound_samples; } + inline int get_layer_samples() { return view_layer.samples; } + inline int get_layer_bound_samples() { return view_layer.bound_samples; } /* get parameters */ static SceneParams get_scene_params(BL::Scene& b_scene, @@ -99,30 +100,33 @@ public: private: /* sync */ - void sync_lamps(bool update_all); - void sync_materials(bool update_all); - void sync_objects(float motion_time = 0.0f); + void sync_lamps(BL::Depsgraph& b_depsgraph, bool update_all); + void sync_materials(BL::Depsgraph& b_depsgraph, bool update_all); + void sync_objects(BL::Depsgraph& b_depsgraph, float motion_time = 0.0f); void sync_motion(BL::RenderSettings& b_render, + BL::Depsgraph& b_depsgraph, BL::Object& b_override, int width, int height, void **python_thread_state); void sync_film(); void sync_view(); - void sync_world(bool update_all); - void sync_shaders(); + void sync_world(BL::Depsgraph& b_depsgraph, bool update_all); + void sync_shaders(BL::Depsgraph& b_depsgraph); void sync_curve_settings(); void sync_nodes(Shader *shader, BL::ShaderNodeTree& b_ntree); - Mesh *sync_mesh(BL::Object& b_ob, bool object_updated, bool hide_tris); + Mesh *sync_mesh(BL::Depsgraph& b_depsgrpah, + BL::Object& b_ob, + BL::Object& b_ob_instance, + bool object_updated, + bool hide_tris); void sync_curves(Mesh *mesh, BL::Mesh& b_mesh, BL::Object& b_ob, bool motion, int motion_step = 0); - Object *sync_object(BL::Object& b_parent, - int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::DupliObject& b_dupli_ob, - Transform& tfm, + Object *sync_object(BL::Depsgraph& b_depsgraph, + BL::Depsgraph::duplis_iterator& b_dupli_iter, uint layer_flag, float motion_time, bool hide_tris, @@ -131,11 +135,13 @@ private: void sync_light(BL::Object& b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object& b_ob, - BL::DupliObject& b_dupli_ob, + BL::Object& b_ob_instance, + int random_id, Transform& tfm, bool *use_portal); void sync_background_light(bool use_portal); - void sync_mesh_motion(BL::Object& b_ob, + void sync_mesh_motion(BL::Depsgraph& b_depsgraph, + BL::Object& b_ob, Object *object, float motion_time); void sync_camera_motion(BL::RenderSettings& b_render, @@ -145,7 +151,7 @@ private: /* particles */ bool sync_dupli_particle(BL::Object& b_ob, - BL::DupliObject& b_dup, + BL::DepsgraphIter& b_dup, Object *object); /* Images. */ @@ -182,31 +188,29 @@ private: struct RenderLayerInfo { RenderLayerInfo() - : scene_layer(0), layer(0), + : view_layer(0), layer(0), holdout_layer(0), exclude_layer(0), material_override(PointerRNA_NULL), use_background_shader(true), use_background_ao(true), use_surfaces(true), use_hair(true), - use_viewport_visibility(false), samples(0), bound_samples(false) {} string name; - uint scene_layer; - uint layer; - uint holdout_layer; - uint exclude_layer; - BL::Material material_override; + uint view_layer; + uint layer; /* This can be safely removed from Cycles. */ + uint holdout_layer; /* This can be safely removed from Cycles. */ + uint exclude_layer; /* This can be safely removed from Cycles. */ + BL::Material material_override; /* This can be safely removed from Cycles. */ bool use_background_shader; bool use_background_ao; bool use_surfaces; bool use_hair; - bool use_viewport_visibility; - int samples; - bool bound_samples; - } render_layer; + int samples; /* This can be safely removed from Cycles. */ + bool bound_samples; /* This can be safely removed from Cycles. */ + } view_layer; Progress &progress; }; diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp index b2e27b76189..a0371a7eed8 100644 --- a/intern/cycles/blender/blender_texture.cpp +++ b/intern/cycles/blender/blender_texture.cpp @@ -34,9 +34,8 @@ void density_texture_space_invert(float3& loc, } /* namespace */ -void point_density_texture_space(BL::Scene& b_scene, +void point_density_texture_space(BL::Depsgraph& b_depsgraph, BL::ShaderNodeTexPointDensity& b_point_density_node, - int settings, float3& loc, float3& size) { @@ -47,8 +46,7 @@ void point_density_texture_space(BL::Scene& b_scene, return; } float3 min, max; - b_point_density_node.calc_point_density_minmax(b_scene, - settings, + b_point_density_node.calc_point_density_minmax(b_depsgraph, &min[0], &max[0]); loc = (min + max) * 0.5f; diff --git a/intern/cycles/blender/blender_texture.h b/intern/cycles/blender/blender_texture.h index 734231a85ec..b4e166c5cdd 100644 --- a/intern/cycles/blender/blender_texture.h +++ b/intern/cycles/blender/blender_texture.h @@ -22,9 +22,8 @@ CCL_NAMESPACE_BEGIN -void point_density_texture_space(BL::Scene& b_scene, +void point_density_texture_space(BL::Depsgraph& b_depsgraph, BL::ShaderNodeTexPointDensity& b_point_density_node, - const int settings, float3& loc, float3& size); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 85bff8f8323..8a874b7063e 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -45,15 +45,15 @@ void python_thread_state_restore(void **python_thread_state); static inline BL::Mesh object_to_mesh(BL::BlendData& data, BL::Object& object, - BL::Scene& scene, + BL::Depsgraph& depsgraph, bool apply_modifiers, - bool render, bool calc_undeformed, Mesh::SubdivisionType subdivision_type) { bool subsurf_mod_show_render = false; bool subsurf_mod_show_viewport = false; + /* TODO: make this work with copy-on-write, modifiers are already evaluated. */ if(subdivision_type != Mesh::SUBDIVISION_NONE) { BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1]; @@ -64,7 +64,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data, subsurf_mod.show_viewport(false); } - BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed); + BL::Mesh me = data.meshes.new_from_object(depsgraph, object, apply_modifiers, false, calc_undeformed); if(subdivision_type != Mesh::SUBDIVISION_NONE) { BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1]; @@ -307,7 +307,7 @@ static inline uint get_layer(const BL::Array<int, 20>& array) static inline uint get_layer(const BL::Array<int, 20>& array, const BL::Array<int, 8>& local_array, bool is_light = false, - uint scene_layers = (1 << 20) - 1) + uint view_layers = (1 << 20) - 1) { uint layer = 0; @@ -319,7 +319,7 @@ static inline uint get_layer(const BL::Array<int, 20>& array, /* Consider light is visible if it was visible without layer * override, which matches behavior of Blender Internal. */ - if(layer & scene_layers) { + if(layer & view_layers) { for(uint i = 0; i < 8; i++) layer |= (1 << (20+i)); } diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 6959dd73c32..906c01c619d 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -78,132 +78,275 @@ std::ostream& operator <<(std::ostream &os, Device::~Device() { - if(!background && vertex_buffer != 0) { - glDeleteBuffers(1, &vertex_buffer); + if(!background) { + if(vertex_buffer != 0) { + glDeleteBuffers(1, &vertex_buffer); + } + if(fallback_shader_program != 0) { + glDeleteProgram(fallback_shader_program); + } } } -void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, - const DeviceDrawParams &draw_params) +/* TODO move shaders to standalone .glsl file. */ +const char *FALLBACK_VERTEX_SHADER = +"#version 330\n" +"uniform vec2 fullscreen;\n" +"in vec2 texCoord;\n" +"in vec2 pos;\n" +"out vec2 texCoord_interp;\n" +"\n" +"vec2 normalize_coordinates()\n" +"{\n" +" return (vec2(2.0) * (pos / fullscreen)) - vec2(1.0);\n" +"}\n" +"\n" +"void main()\n" +"{\n" +" gl_Position = vec4(normalize_coordinates(), 0.0, 1.0);\n" +" texCoord_interp = texCoord;\n" +"}\n\0"; + +const char *FALLBACK_FRAGMENT_SHADER = +"#version 330\n" +"uniform sampler2D image_texture;\n" +"in vec2 texCoord_interp;\n" +"out vec4 fragColor;\n" +"\n" +"void main()\n" +"{\n" +" fragColor = texture(image_texture, texCoord_interp);\n" +"}\n\0"; + +static void shader_print_errors(const char *task, const char *log, const char *code) { - assert(rgba.type == MEM_PIXELS); + LOG(ERROR) << "Shader: " << task << " error:"; + LOG(ERROR) << "===== shader string ===="; - mem_copy_from(rgba, y, w, h, rgba.memory_elements_size(1)); + stringstream stream(code); + string partial; - if(transparent) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + int line = 1; + while(getline(stream, partial, '\n')) { + if(line < 10) { + LOG(ERROR) << " " << line << " " << partial; + } + else { + LOG(ERROR) << line << " " << partial; + } + line++; } + LOG(ERROR) << log; +} - glColor3f(1.0f, 1.0f, 1.0f); +static int bind_fallback_shader(void) +{ + GLint status; + GLchar log[5000]; + GLsizei length = 0; + GLuint program = 0; - if(rgba.data_type == TYPE_HALF) { - /* for multi devices, this assumes the inefficient method that we allocate - * all pixels on the device even though we only render to a subset */ - GLhalf *host_pointer = (GLhalf*)rgba.host_pointer; - float vbuffer[16], *basep; - float *vp = NULL; - - host_pointer += 4*y*w; - - /* draw half float texture, GLSL shader for display transform assumed to be bound */ - GLuint texid; - glGenTextures(1, &texid); - glBindTexture(GL_TEXTURE_2D, texid); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGBA, GL_HALF_FLOAT, host_pointer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glEnable(GL_TEXTURE_2D); - - if(draw_params.bind_display_space_shader_cb) { - draw_params.bind_display_space_shader_cb(); + struct Shader { + const char *source; + GLenum type; + } shaders[2] = { + {FALLBACK_VERTEX_SHADER, GL_VERTEX_SHADER}, + {FALLBACK_FRAGMENT_SHADER, GL_FRAGMENT_SHADER} + }; + + program = glCreateProgram(); + + for(int i = 0; i < 2; i++) { + GLuint shader = glCreateShader(shaders[i].type); + + string source_str = shaders[i].source; + const char *c_str = source_str.c_str(); + + glShaderSource(shader, 1, &c_str, NULL); + glCompileShader(shader); + + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + if(!status) { + glGetShaderInfoLog(shader, sizeof(log), &length, log); + shader_print_errors("compile", log, c_str); + return 0; } - if(GLEW_VERSION_1_5) { - if(!vertex_buffer) - glGenBuffers(1, &vertex_buffer); + glAttachShader(program, shader); + } + + /* Link output. */ + glBindFragDataLocation(program, 0, "fragColor"); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */ - glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW); + /* Link and error check. */ + glLinkProgram(program); + + glGetProgramiv(program, GL_LINK_STATUS, &status); + if(!status) { + glGetShaderInfoLog(program, sizeof(log), &length, log); + shader_print_errors("linking", log, FALLBACK_VERTEX_SHADER); + shader_print_errors("linking", log, FALLBACK_FRAGMENT_SHADER); + return 0; + } + + return program; +} + +bool Device::bind_fallback_display_space_shader(const float width, const float height) +{ + if(fallback_status == FALLBACK_SHADER_STATUS_ERROR) { + return false; + } - vp = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + if(fallback_status == FALLBACK_SHADER_STATUS_NONE) { + fallback_shader_program = bind_fallback_shader(); + fallback_status = FALLBACK_SHADER_STATUS_ERROR; - basep = NULL; + if (fallback_shader_program == 0) { + return false; } - else { - basep = vbuffer; - vp = vbuffer; + + glUseProgram(fallback_shader_program); + image_texture_location = glGetUniformLocation(fallback_shader_program, "image_texture"); + if(image_texture_location < 0) { + LOG(ERROR) << "Shader doesn't containt the 'image_texture' uniform."; + return false; } - if(vp) { - /* texture coordinate - vertex pair */ - vp[0] = 0.0f; - vp[1] = 0.0f; - vp[2] = dx; - vp[3] = dy; - - vp[4] = 1.0f; - vp[5] = 0.0f; - vp[6] = (float)width + dx; - vp[7] = dy; - - vp[8] = 1.0f; - vp[9] = 1.0f; - vp[10] = (float)width + dx; - vp[11] = (float)height + dy; - - vp[12] = 0.0f; - vp[13] = 1.0f; - vp[14] = dx; - vp[15] = (float)height + dy; - - if(vertex_buffer) - glUnmapBuffer(GL_ARRAY_BUFFER); + fullscreen_location = glGetUniformLocation(fallback_shader_program, "fullscreen"); + if(fullscreen_location < 0) { + LOG(ERROR) << "Shader doesn't containt the 'fullscreen' uniform."; + return false; } - glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), basep); - glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), ((char *)basep) + 2 * sizeof(float)); + fallback_status = FALLBACK_SHADER_STATUS_SUCCESS; + } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + /* Run this every time. */ + glUseProgram(fallback_shader_program); + glUniform1i(image_texture_location, 0); + glUniform2f(fullscreen_location, width, height); + return true; +} - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +void Device::draw_pixels( + device_memory& rgba, int y, + int w, int h, int width, int height, + int dx, int dy, int dw, int dh, + bool transparent, const DeviceDrawParams &draw_params) +{ + const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + assert(rgba.type == MEM_PIXELS); + mem_copy_from(rgba, y, w, h, rgba.memory_elements_size(1)); - if(vertex_buffer) { - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + GLuint texid; + glGenTextures(1, &texid); + glBindTexture(GL_TEXTURE_2D, texid); - if(draw_params.unbind_display_space_shader_cb) { - draw_params.unbind_display_space_shader_cb(); - } + if(rgba.data_type == TYPE_HALF) { + GLhalf *data_pointer = (GLhalf*)rgba.host_pointer; + data_pointer += 4 * y * w; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, data_pointer); + } + else { + uint8_t *data_pointer = (uint8_t*)rgba.host_pointer; + data_pointer += 4 * y * w; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_pointer); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + if(transparent) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - glDeleteTextures(1, &texid); + GLint shader_program; + if(use_fallback_shader) { + if (!bind_fallback_display_space_shader(dw, dh)) { + return; + } + shader_program = fallback_shader_program; } else { - /* fallback for old graphics cards that don't support GLSL, half float, - * and non-power-of-two textures */ - glPixelZoom((float)width/(float)w, (float)height/(float)h); - glRasterPos2f(dx, dy); + draw_params.bind_display_space_shader_cb(); + glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program); + } + + if(!vertex_buffer) { + glGenBuffers(1, &vertex_buffer); + } + + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */ + glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW); + + float *vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - uint8_t *pixels = (uint8_t*)rgba.host_pointer; + if(vpointer) { + /* texture coordinate - vertex pair */ + vpointer[0] = 0.0f; + vpointer[1] = 0.0f; + vpointer[2] = dx; + vpointer[3] = dy; - pixels += 4*y*w; + vpointer[4] = 1.0f; + vpointer[5] = 0.0f; + vpointer[6] = (float)width + dx; + vpointer[7] = dy; - glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + vpointer[8] = 1.0f; + vpointer[9] = 1.0f; + vpointer[10] = (float)width + dx; + vpointer[11] = (float)height + dy; - glRasterPos2f(0.0f, 0.0f); - glPixelZoom(1.0f, 1.0f); + vpointer[12] = 0.0f; + vpointer[13] = 1.0f; + vpointer[14] = dx; + vpointer[15] = (float)height + dy; + + if(vertex_buffer) { + glUnmapBuffer(GL_ARRAY_BUFFER); + } + } + + GLuint vertex_array_object; + GLuint position_attribute, texcoord_attribute; + + glGenVertexArrays(1, &vertex_array_object); + glBindVertexArray(vertex_array_object); + + texcoord_attribute = glGetAttribLocation(shader_program, "texCoord"); + position_attribute = glGetAttribLocation(shader_program, "pos"); + + glEnableVertexAttribArray(texcoord_attribute); + glEnableVertexAttribArray(position_attribute); + + glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0); + glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)(sizeof(float) * 2)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + if(vertex_buffer) { + glBindBuffer(GL_ARRAY_BUFFER, 0); } - if(transparent) + if(use_fallback_shader) { + glUseProgram(0); + } + else { + draw_params.unbind_display_space_shader_cb(); + } + + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &texid); + + if(transparent) { glDisable(GL_BLEND); + } } Device *Device::create(DeviceInfo& info, Stats &stats, bool background) diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index b856bdd9d01..31deba2d796 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -249,13 +249,26 @@ struct DeviceDrawParams { class Device { friend class device_sub_ptr; protected: - Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), vertex_buffer(0), info(info_), stats(stats_) {} + enum { + FALLBACK_SHADER_STATUS_NONE = 0, + FALLBACK_SHADER_STATUS_ERROR, + FALLBACK_SHADER_STATUS_SUCCESS, + }; + + Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), + vertex_buffer(0), + fallback_status(FALLBACK_SHADER_STATUS_NONE), fallback_shader_program(0), + info(info_), stats(stats_) {} bool background; string error_msg; /* used for real time display */ unsigned int vertex_buffer; + int fallback_status, fallback_shader_program; + int image_texture_location, fullscreen_location; + + bool bind_fallback_display_space_shader(const float width, const float height); virtual device_ptr mem_alloc_sub_ptr(device_memory& /*mem*/, int /*offset*/, int /*size*/) { @@ -306,9 +319,10 @@ public: virtual void task_cancel() = 0; /* opengl drawing */ - virtual void draw_pixels(device_memory& mem, int y, int w, int h, - int dx, int dy, int width, int height, bool transparent, - const DeviceDrawParams &draw_params); + virtual void draw_pixels(device_memory& mem, int y, + int w, int h, int width, int height, + int dx, int dy, int dw, int dh, + bool transparent, const DeviceDrawParams &draw_params); #ifdef WITH_NETWORK /* networking */ diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index b4529feffa7..b1bc417ba4f 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -1893,7 +1893,7 @@ public: glGenTextures(1, &pmem.cuTexId); glBindTexture(GL_TEXTURE_2D, pmem.cuTexId); if(mem.data_type == TYPE_HALF) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL); else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, pmem.w, pmem.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -1953,12 +1953,16 @@ public: } } - void draw_pixels(device_memory& mem, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, + void draw_pixels( + device_memory& mem, int y, + int w, int h, int width, int height, + int dx, int dy, int dw, int dh, bool transparent, const DeviceDrawParams &draw_params) { assert(mem.type == MEM_PIXELS); if(!background) { + const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL); PixelMem pmem = pixel_mem_map[mem.device_pointer]; float *vpointer; @@ -1975,27 +1979,34 @@ public: glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO); glBindTexture(GL_TEXTURE_2D, pmem.cuTexId); - if(mem.data_type == TYPE_HALF) + if(mem.data_type == TYPE_HALF) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_HALF_FLOAT, (void*)offset); - else + } + else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)offset); + } glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glEnable(GL_TEXTURE_2D); - if(transparent) { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } - glColor3f(1.0f, 1.0f, 1.0f); - - if(draw_params.bind_display_space_shader_cb) { + GLint shader_program; + if(use_fallback_shader) { + if(!bind_fallback_display_space_shader(dw, dh)) { + return; + } + shader_program = fallback_shader_program; + } + else { draw_params.bind_display_space_shader_cb(); + glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program); } - if(!vertex_buffer) + if(!vertex_buffer) { glGenBuffers(1, &vertex_buffer); + } glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */ @@ -2028,33 +2039,40 @@ public: glUnmapBuffer(GL_ARRAY_BUFFER); } - glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0); - glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)NULL + 2 * sizeof(float)); + GLuint vertex_array_object; + GLuint position_attribute, texcoord_attribute; - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glGenVertexArrays(1, &vertex_array_object); + glBindVertexArray(vertex_array_object); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + texcoord_attribute = glGetAttribLocation(shader_program, "texCoord"); + position_attribute = glGetAttribLocation(shader_program, "pos"); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + glEnableVertexAttribArray(texcoord_attribute); + glEnableVertexAttribArray(position_attribute); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0); + glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)(sizeof(float) * 2)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if(draw_params.unbind_display_space_shader_cb) { + if(use_fallback_shader) { + glUseProgram(0); + } + else { draw_params.unbind_display_space_shader_cb(); } - if(transparent) + if(transparent) { glDisable(GL_BLEND); + } glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); return; } - Device::draw_pixels(mem, y, w, h, dx, dy, width, height, transparent, draw_params); + Device::draw_pixels(mem, y, w, h, width, height, dx, dy, dw, dh, transparent, draw_params); } void thread_run(DeviceTask *task) diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 3a4c08b6eb2..91507e6be0c 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -216,8 +216,11 @@ public: sub.device->const_copy_to(name, host, size); } - void draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, - const DeviceDrawParams &draw_params) + void draw_pixels( + device_memory& rgba, int y, + int w, int h, int width, int height, + int dx, int dy, int dw, int dh, + bool transparent, const DeviceDrawParams &draw_params) { device_ptr key = rgba.device_pointer; int i = 0, sub_h = h/devices.size(); @@ -231,7 +234,7 @@ public: /* adjust math for w/width */ rgba.device_pointer = sub.ptr_map[key]; - sub.device->draw_pixels(rgba, sy, w, sh, dx, sdy, width, sheight, transparent, draw_params); + sub.device->draw_pixels(rgba, sy, w, sh, width, sheight, dx, sdy, dw, dh, transparent, draw_params); i++; } diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index ec7203d36eb..b1be0b2155a 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -44,7 +44,7 @@ typedef struct LightSample { * * Note: light_p is modified when sample_coord is true. */ -ccl_device_inline float area_light_sample(float3 P, +ccl_device_inline float rect_light_sample(float3 P, float3 *light_p, float3 axisu, float3 axisv, float randu, float randv, @@ -125,6 +125,60 @@ ccl_device_inline float area_light_sample(float3 P, return 0.0f; } +ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv) +{ + to_unit_disk(&randu, &randv); + return ru*randu + rv*randv; +} + +ccl_device float3 disk_light_sample(float3 v, float randu, float randv) +{ + float3 ru, rv; + + make_orthonormals(v, &ru, &rv); + + return ellipse_sample(ru, rv, randu, randv); +} + +ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv) +{ + return normalize(D + disk_light_sample(D, randu, randv)*radius); +} + +ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv) +{ + return disk_light_sample(normalize(P - center), randu, randv)*radius; +} + +ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls) +{ + float3 I = ls->Ng; + + float attenuation = dot(dir, I); + + if(attenuation <= spot_angle) { + attenuation = 0.0f; + } + else { + float t = attenuation - spot_angle; + + if(t < spot_smooth && spot_smooth != 0.0f) + attenuation *= smoothstepf(t/spot_smooth); + } + + return attenuation; +} + +ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) +{ + float cos_pi = dot(Ng, I); + + if(cos_pi <= 0.0f) + return 0.0f; + + return t*t/cos_pi; +} + /* Background Light */ #ifdef __BACKGROUND_MIS__ @@ -295,11 +349,19 @@ ccl_device_inline float background_portal_pdf(KernelGlobals *kg, const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); + bool is_round = (klight->area.invarea < 0.0f); - if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL)) + if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL, is_round)) continue; - portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false); + if(is_round) { + float t; + float3 D = normalize_len(lightpos - P, &t); + portal_pdf += fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t); + } + else { + portal_pdf += rect_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false); + } } if(ignore_portal >= 0) { @@ -349,15 +411,26 @@ ccl_device float3 background_portal_sample(KernelGlobals *kg, const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); - - *pdf = area_light_sample(P, &lightpos, - axisu, axisv, - randu, randv, - true); + bool is_round = (klight->area.invarea < 0.0f); + + float3 D; + if(is_round) { + lightpos += ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv); + float t; + D = normalize_len(lightpos - P, &t); + *pdf = fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t); + } + else { + *pdf = rect_light_sample(P, &lightpos, + axisu, axisv, + randu, randv, + true); + D = normalize(lightpos - P); + } *pdf /= num_possible; *sampled_portal = p; - return normalize(lightpos - P); + return D; } portal--; @@ -458,55 +531,6 @@ ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direct /* Regular Light */ -ccl_device float3 disk_light_sample(float3 v, float randu, float randv) -{ - float3 ru, rv; - - make_orthonormals(v, &ru, &rv); - to_unit_disk(&randu, &randv); - - return ru*randu + rv*randv; -} - -ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv) -{ - return normalize(D + disk_light_sample(D, randu, randv)*radius); -} - -ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv) -{ - return disk_light_sample(normalize(P - center), randu, randv)*radius; -} - -ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls) -{ - float3 I = ls->Ng; - - float attenuation = dot(dir, I); - - if(attenuation <= spot_angle) { - attenuation = 0.0f; - } - else { - float t = attenuation - spot_angle; - - if(t < spot_smooth && spot_smooth != 0.0f) - attenuation *= smoothstepf(t/spot_smooth); - } - - return attenuation; -} - -ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t) -{ - float cos_pi = dot(Ng, I); - - if(cos_pi <= 0.0f) - return 0.0f; - - return t*t/cos_pi; -} - ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, int lamp, float randu, float randv, @@ -601,26 +625,39 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); + float invarea = fabsf(klight->area.invarea); + bool is_round = (klight->area.invarea < 0.0f); if(dot(ls->P - P, D) > 0.0f) { return false; } - float3 inplane = ls->P; - ls->pdf = area_light_sample(P, &ls->P, - axisu, axisv, - randu, randv, - true); + float3 inplane; + + if(is_round) { + inplane = ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv); + ls->P += inplane; + ls->pdf = invarea; + } + else { + inplane = ls->P; + ls->pdf = rect_light_sample(P, &ls->P, + axisu, axisv, + randu, randv, + true); + inplane = ls->P - inplane; + } - inplane = ls->P - inplane; ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f; ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f; ls->Ng = D; ls->D = normalize_len(ls->P - P, &ls->t); - float invarea = klight->area.invarea; ls->eval_fac = 0.25f*invarea; + if(is_round) { + ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t); + } } } @@ -731,7 +768,8 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, } else if(type == LIGHT_AREA) { /* area light */ - float invarea = klight->area.invarea; + float invarea = fabsf(klight->area.invarea); + bool is_round = (klight->area.invarea < 0.0f); if(invarea == 0.0f) return false; @@ -754,14 +792,20 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, if(!ray_quad_intersect(P, D, 0.0f, t, light_P, axisu, axisv, Ng, &ls->P, &ls->t, - &ls->u, &ls->v)) + &ls->u, &ls->v, + is_round)) { return false; } ls->D = D; ls->Ng = Ng; - ls->pdf = area_light_sample(P, &light_P, axisu, axisv, 0, 0, false); + if(is_round) { + ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t); + } + else { + ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false); + } ls->eval_fac = 0.25f*invarea; } else { diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 6f560380b40..91b739741bb 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -438,7 +438,11 @@ void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params) device_memory& rgba = (half_float)? (device_memory&)rgba_half: (device_memory&)rgba_byte; - device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params); + device->draw_pixels( + rgba, 0, + draw_width, draw_height, params.width, params.height, + params.full_x, params.full_y, params.full_width, params.full_height, + transparent, draw_params); } } diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index cbcd2564e6e..d45d4543e16 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -119,6 +119,7 @@ NODE_DEFINE(Light) SOCKET_FLOAT(sizeu, "Size U", 1.0f); SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_FLOAT(sizev, "Size V", 1.0f); + SOCKET_BOOLEAN(round, "Round", false); SOCKET_INT(map_resolution, "Map Resolution", 512); @@ -735,12 +736,15 @@ void LightManager::device_update_points(Device *, float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); float area = len(axisu)*len(axisv); - float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + if(light->round) { + area *= -M_PI_4_F; + } + float invarea = (area != 0.0f)? 1.0f/area: 1.0f; float3 dir = light->dir; dir = safe_normalize(dir); - if(light->use_mis && area > 0.0f) + if(light->use_mis && area != 0.0f) shader_id |= SHADER_USE_MIS; klights[light_index].co[0] = co.x; @@ -808,7 +812,10 @@ void LightManager::device_update_points(Device *, float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); float area = len(axisu)*len(axisv); - float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + if(light->round) { + area *= -M_PI_4_F; + } + float invarea = (area != 0.0f)? 1.0f/area: 1.0f; float3 dir = light->dir; dir = safe_normalize(dir); diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 5f8677ee2f2..acbbdd15ddf 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -51,6 +51,7 @@ public: float sizeu; float3 axisv; float sizev; + bool round; Transform tfm; diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 61ddcc38f50..5f15487df57 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -186,12 +186,17 @@ ccl_device_forceinline bool ray_triangle_intersect( #undef dot3 } +/* Tests for an intersection between a ray and a quad defined by + * its midpoint, normal and sides. + * If ellipse is true, hits outside the ellipse that's enclosed by the + * quad are rejected. + */ ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n, float3 *isect_P, float *isect_t, - float *isect_u, float *isect_v) + float *isect_u, float *isect_v, bool ellipse) { /* Perform intersection test. */ float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n); @@ -200,20 +205,23 @@ ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, } const float3 hit = ray_P + t*ray_D; const float3 inplane = hit - quad_P; - const float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f; - if(u < 0.0f || u > 1.0f) { + const float u = dot(inplane, quad_u) / dot(quad_u, quad_u); + if(u < -0.5f || u > 0.5f) { + return false; + } + const float v = dot(inplane, quad_v) / dot(quad_v, quad_v); + if(v < -0.5f || v > 0.5f) { return false; } - const float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f; - if(v < 0.0f || v > 1.0f) { + if(ellipse && (u*u + v*v > 0.25f)) { return false; } /* Store the result. */ /* TODO(sergey): Check whether we can avoid some checks here. */ if(isect_P != NULL) *isect_P = hit; if(isect_t != NULL) *isect_t = t; - if(isect_u != NULL) *isect_u = u; - if(isect_v != NULL) *isect_v = v; + if(isect_u != NULL) *isect_u = u + 0.5f; + if(isect_v != NULL) *isect_v = v + 0.5f; return true; } diff --git a/intern/cycles/util/util_opengl.h b/intern/cycles/util/util_opengl.h index 0b5462e0a09..7a8d5eec1f9 100644 --- a/intern/cycles/util/util_opengl.h +++ b/intern/cycles/util/util_opengl.h @@ -20,12 +20,6 @@ /* OpenGL header includes, used everywhere we use OpenGL, to deal with * platform differences in one central place. */ -#ifdef WITH_GLEW_MX -# include "glew-mx.h" -#else -# include <GL/glew.h> -# define mxCreateContext() glewInit() -# define mxMakeCurrentContext(x) (x) -#endif +#include <GL/glew.h> #endif /* __UTIL_OPENGL_H__ */ diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp index 10d86167921..7b453d123b8 100644 --- a/intern/cycles/util/util_view.cpp +++ b/intern/cycles/util/util_view.cpp @@ -252,7 +252,7 @@ void view_main_loop(const char *title, int width, int height, glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH); glutCreateWindow(title); - mxMakeCurrentContext(mxCreateContext()); + glewInit(); view_reshape(width, height); |