Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r--intern/cycles/blender/addon/__init__.py31
-rw-r--r--intern/cycles/blender/addon/engine.py49
-rw-r--r--intern/cycles/blender/addon/presets.py4
-rw-r--r--intern/cycles/blender/addon/properties.py2143
-rw-r--r--intern/cycles/blender/addon/ui.py2009
-rw-r--r--intern/cycles/blender/addon/version_update.py113
-rw-r--r--intern/cycles/blender/blender_camera.cpp21
-rw-r--r--intern/cycles/blender/blender_curves.cpp60
-rw-r--r--intern/cycles/blender/blender_mesh.cpp264
-rw-r--r--intern/cycles/blender/blender_object.cpp376
-rw-r--r--intern/cycles/blender/blender_particles.cpp8
-rw-r--r--intern/cycles/blender/blender_python.cpp92
-rw-r--r--intern/cycles/blender/blender_session.cpp472
-rw-r--r--intern/cycles/blender/blender_session.h30
-rw-r--r--intern/cycles/blender/blender_shader.cpp142
-rw-r--r--intern/cycles/blender/blender_sync.cpp324
-rw-r--r--intern/cycles/blender/blender_sync.h74
-rw-r--r--intern/cycles/blender/blender_texture.cpp6
-rw-r--r--intern/cycles/blender/blender_texture.h3
-rw-r--r--intern/cycles/blender/blender_util.h66
20 files changed, 3171 insertions, 3116 deletions
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 038126278aa..d222b4c8038 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(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)
+
+ engine.reset(self, context.blend_data, context.depsgraph)
+ engine.sync(self, context.depsgraph, context.blend_data)
def view_draw(self, context):
- engine.draw(self, context.region, context.space_data, context.region_data)
+ 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 83b9a8eee0c..b8bc74f9e35 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -81,7 +81,7 @@ def _parse_command_line():
return
parser = _configure_argument_parser()
- args, unknown = parser.parse_known_args(argv[argv.index("--") + 1:])
+ args, _ = parser.parse_known_args(argv[argv.index("--") + 1:])
if args.cycles_resumable_num_chunks is not None:
if args.cycles_resumable_current_chunk is not None:
@@ -133,13 +133,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()
+ prefs = bpy.context.preferences.as_pointer()
if region:
region = region.as_pointer()
if v3d:
@@ -147,12 +146,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(), prefs, data, region, v3d, rv3d, preview_osl)
def free(engine):
@@ -163,38 +158,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.as_pointer())
+ 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():
@@ -253,8 +256,6 @@ def register_passes(engine, scene, srl):
if crl.use_pass_volume_direct: engine.register_pass(scene, srl, "VolumeDir", 3, "RGB", 'COLOR')
if crl.use_pass_volume_indirect: engine.register_pass(scene, srl, "VolumeInd", 3, "RGB", 'COLOR')
- cscene = scene.cycles
-
if crl.use_pass_crypto_object:
for i in range(0, crl.pass_crypto_depth, 2):
engine.register_pass(scene, srl, "CryptoObject" + '{:02d}'.format(i), 4, "RGBA", 'COLOR')
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index 17efb00abdb..78a8605e93f 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -24,7 +24,7 @@ class AddPresetIntegrator(AddPresetBase, Operator):
'''Add an Integrator Preset'''
bl_idname = "render.cycles_integrator_preset_add"
bl_label = "Add Integrator Preset"
- preset_menu = "CYCLES_MT_integrator_presets"
+ preset_menu = "CYCLES_PT_integrator_presets"
preset_defines = [
"cycles = bpy.context.scene.cycles"
@@ -49,7 +49,7 @@ class AddPresetSampling(AddPresetBase, Operator):
'''Add a Sampling Preset'''
bl_idname = "render.cycles_sampling_preset_add"
bl_label = "Add Sampling Preset"
- preset_menu = "CYCLES_MT_sampling_presets"
+ preset_menu = "CYCLES_PT_sampling_presets"
preset_defines = [
"cycles = bpy.context.scene.cycles"
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 23ab1cf6a30..c60db9ffc2b 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -17,12 +17,16 @@
# <pep8 compliant>
import bpy
-from bpy.props import (BoolProperty,
- EnumProperty,
- FloatProperty,
- IntProperty,
- PointerProperty,
- StringProperty)
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ PointerProperty,
+ StringProperty,
+)
+
+from math import pi
# enums
@@ -154,586 +158,591 @@ enum_texture_limit = (
class CyclesRenderSettings(bpy.types.PropertyGroup):
- @classmethod
- def register(cls):
- bpy.types.Scene.cycles = PointerProperty(
- name="Cycles Render Settings",
- description="Cycles render settings",
- type=cls,
- )
- cls.device = EnumProperty(
- name="Device",
- description="Device to use for rendering",
- items=enum_devices,
- default='CPU',
- )
- cls.feature_set = EnumProperty(
- name="Feature Set",
- description="Feature set to use for rendering",
- items=enum_feature_set,
- default='SUPPORTED',
- )
- cls.shading_system = BoolProperty(
- name="Open Shading Language",
- description="Use Open Shading Language (CPU rendering only)",
- )
- cls.progressive = EnumProperty(
- name="Integrator",
- description="Method to sample lights and materials",
- items=enum_integrator,
- default='PATH',
- )
+ device: EnumProperty(
+ name="Device",
+ description="Device to use for rendering",
+ items=enum_devices,
+ default='CPU',
+ )
+ feature_set: EnumProperty(
+ name="Feature Set",
+ description="Feature set to use for rendering",
+ items=enum_feature_set,
+ default='SUPPORTED',
+ )
+ shading_system: BoolProperty(
+ name="Open Shading Language",
+ description="Use Open Shading Language (CPU rendering only)",
+ )
- cls.use_square_samples = BoolProperty(
- name="Square Samples",
- description="Square sampling values for easier artist control",
- default=False,
- )
+ progressive: EnumProperty(
+ name="Integrator",
+ description="Method to sample lights and materials",
+ items=enum_integrator,
+ default='PATH',
+ )
- cls.samples = IntProperty(
- name="Samples",
- description="Number of samples to render for each pixel",
- min=1, max=2147483647,
- default=128,
- )
- cls.preview_samples = IntProperty(
- name="Preview Samples",
- description="Number of samples to render in the viewport, unlimited if 0",
- min=0, max=2147483647,
- default=32,
- )
- cls.preview_pause = BoolProperty(
- name="Pause Preview",
- 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,
- )
+ use_square_samples: BoolProperty(
+ name="Square Samples",
+ description="Square sampling values for easier artist control",
+ default=False,
+ )
- cls.aa_samples = IntProperty(
- name="AA Samples",
- description="Number of antialiasing samples to render for each pixel",
- min=1, max=2097151,
- default=128,
- )
- cls.preview_aa_samples = IntProperty(
- name="AA Samples",
- description="Number of antialiasing samples to render in the viewport, unlimited if 0",
- min=0, max=2097151,
- default=32,
- )
- cls.diffuse_samples = IntProperty(
- name="Diffuse Samples",
- description="Number of diffuse bounce samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
- cls.glossy_samples = IntProperty(
- name="Glossy Samples",
- description="Number of glossy bounce samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
- cls.transmission_samples = IntProperty(
- name="Transmission Samples",
- description="Number of transmission bounce samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
- cls.ao_samples = IntProperty(
- name="Ambient Occlusion Samples",
- description="Number of ambient occlusion samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
- cls.mesh_light_samples = IntProperty(
- name="Mesh Light Samples",
- description="Number of mesh emission light samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
+ samples: IntProperty(
+ name="Samples",
+ description="Number of samples to render for each pixel",
+ min=1, max=2147483647,
+ default=128,
+ )
+ preview_samples: IntProperty(
+ name="Preview Samples",
+ description="Number of samples to render in the viewport, unlimited if 0",
+ min=0, max=2147483647,
+ default=32,
+ )
+ preview_pause: BoolProperty(
+ name="Pause Preview",
+ description="Pause all viewport preview renders",
+ default=False,
+ )
+ aa_samples: IntProperty(
+ name="AA Samples",
+ description="Number of antialiasing samples to render for each pixel",
+ min=1, max=2097151,
+ default=128,
+ )
+ preview_aa_samples: IntProperty(
+ name="AA Samples",
+ description="Number of antialiasing samples to render in the viewport, unlimited if 0",
+ min=0, max=2097151,
+ default=32,
+ )
+ diffuse_samples: IntProperty(
+ name="Diffuse Samples",
+ description="Number of diffuse bounce samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
+ glossy_samples: IntProperty(
+ name="Glossy Samples",
+ description="Number of glossy bounce samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
+ transmission_samples: IntProperty(
+ name="Transmission Samples",
+ description="Number of transmission bounce samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
+ ao_samples: IntProperty(
+ name="Ambient Occlusion Samples",
+ description="Number of ambient occlusion samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
+ mesh_light_samples: IntProperty(
+ name="Mesh Light Samples",
+ description="Number of mesh emission light samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
- cls.subsurface_samples = IntProperty(
- name="Subsurface Samples",
- description="Number of subsurface scattering samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
+ subsurface_samples: IntProperty(
+ name="Subsurface Samples",
+ description="Number of subsurface scattering samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
- cls.volume_samples = IntProperty(
- name="Volume Samples",
- description="Number of volume scattering samples to render for each AA sample",
- min=1, max=1024,
- default=1,
- )
+ volume_samples: IntProperty(
+ name="Volume Samples",
+ description="Number of volume scattering samples to render for each AA sample",
+ min=1, max=1024,
+ default=1,
+ )
- cls.sampling_pattern = EnumProperty(
- name="Sampling Pattern",
- description="Random sampling pattern used by the integrator",
- items=enum_sampling_pattern,
- default='SOBOL',
- )
+ sampling_pattern: EnumProperty(
+ name="Sampling Pattern",
+ description="Random sampling pattern used by the integrator",
+ items=enum_sampling_pattern,
+ default='SOBOL',
+ )
- cls.use_layer_samples = EnumProperty(
- name="Layer Samples",
- description="How to use per render layer sample settings",
- items=enum_use_layer_samples,
- default='USE',
- )
+ use_layer_samples: EnumProperty(
+ name="Layer Samples",
+ description="How to use per view layer sample settings",
+ items=enum_use_layer_samples,
+ default='USE',
+ )
- cls.sample_all_lights_direct = BoolProperty(
- name="Sample All Direct Lights",
- description="Sample all lights (for direct samples), rather than randomly picking one",
- default=True,
- )
+ sample_all_lights_direct: BoolProperty(
+ name="Sample All Direct Lights",
+ description="Sample all lights (for direct samples), rather than randomly picking one",
+ default=True,
+ )
- cls.sample_all_lights_indirect = BoolProperty(
- name="Sample All Indirect Lights",
- description="Sample all lights (for indirect samples), rather than randomly picking one",
- default=True,
- )
- cls.light_sampling_threshold = FloatProperty(
- name="Light Sampling Threshold",
- description="Probabilistically terminate light samples when the light contribution is below this threshold (more noise but faster rendering). "
- "Zero disables the test and never ignores lights",
- min=0.0, max=1.0,
- default=0.01,
- )
+ sample_all_lights_indirect: BoolProperty(
+ name="Sample All Indirect Lights",
+ description="Sample all lights (for indirect samples), rather than randomly picking one",
+ default=True,
+ )
+ light_sampling_threshold: FloatProperty(
+ name="Light Sampling Threshold",
+ description="Probabilistically terminate light samples when the light contribution is below this threshold (more noise but faster rendering). "
+ "Zero disables the test and never ignores lights",
+ min=0.0, max=1.0,
+ default=0.01,
+ )
- cls.caustics_reflective = BoolProperty(
- name="Reflective Caustics",
- description="Use reflective caustics, resulting in a brighter image (more noise but added realism)",
- default=True,
- )
+ caustics_reflective: BoolProperty(
+ name="Reflective Caustics",
+ description="Use reflective caustics, resulting in a brighter image (more noise but added realism)",
+ default=True,
+ )
- cls.caustics_refractive = BoolProperty(
- name="Refractive Caustics",
- description="Use refractive caustics, resulting in a brighter image (more noise but added realism)",
- default=True,
- )
+ caustics_refractive: BoolProperty(
+ name="Refractive Caustics",
+ description="Use refractive caustics, resulting in a brighter image (more noise but added realism)",
+ default=True,
+ )
- cls.blur_glossy = FloatProperty(
- name="Filter Glossy",
- description="Adaptively blur glossy shaders after blurry bounces, "
- "to reduce noise at the cost of accuracy",
- min=0.0, max=10.0,
- default=1.0,
- )
+ blur_glossy: FloatProperty(
+ name="Filter Glossy",
+ description="Adaptively blur glossy shaders after blurry bounces, "
+ "to reduce noise at the cost of accuracy",
+ min=0.0, max=10.0,
+ default=1.0,
+ )
- cls.max_bounces = IntProperty(
- name="Max Bounces",
- description="Total maximum number of bounces",
- min=0, max=1024,
- default=12,
- )
+ max_bounces: IntProperty(
+ name="Max Bounces",
+ description="Total maximum number of bounces",
+ min=0, max=1024,
+ default=12,
+ )
- cls.diffuse_bounces = IntProperty(
- name="Diffuse Bounces",
- description="Maximum number of diffuse reflection bounces, bounded by total maximum",
- min=0, max=1024,
- default=4,
- )
- cls.glossy_bounces = IntProperty(
- name="Glossy Bounces",
- description="Maximum number of glossy reflection bounces, bounded by total maximum",
- min=0, max=1024,
- default=4,
- )
- cls.transmission_bounces = IntProperty(
- name="Transmission Bounces",
- description="Maximum number of transmission bounces, bounded by total maximum",
- min=0, max=1024,
- default=12,
- )
- cls.volume_bounces = IntProperty(
- name="Volume Bounces",
- description="Maximum number of volumetric scattering events",
- min=0, max=1024,
- default=0,
- )
+ diffuse_bounces: IntProperty(
+ name="Diffuse Bounces",
+ description="Maximum number of diffuse reflection bounces, bounded by total maximum",
+ min=0, max=1024,
+ default=4,
+ )
+ glossy_bounces: IntProperty(
+ name="Glossy Bounces",
+ description="Maximum number of glossy reflection bounces, bounded by total maximum",
+ min=0, max=1024,
+ default=4,
+ )
+ transmission_bounces: IntProperty(
+ name="Transmission Bounces",
+ description="Maximum number of transmission bounces, bounded by total maximum",
+ min=0, max=1024,
+ default=12,
+ )
+ volume_bounces: IntProperty(
+ name="Volume Bounces",
+ description="Maximum number of volumetric scattering events",
+ min=0, max=1024,
+ default=0,
+ )
- cls.transparent_max_bounces = IntProperty(
- name="Transparent Max Bounces",
- description="Maximum number of transparent bounces",
- min=0, max=1024,
- default=8,
- )
+ transparent_max_bounces: IntProperty(
+ name="Transparent Max Bounces",
+ description="Maximum number of transparent bounces",
+ min=0, max=1024,
+ default=8,
+ )
- cls.volume_step_size = FloatProperty(
- name="Step Size",
- description="Distance between volume shader samples when rendering the volume "
- "(lower values give more accurate and detailed results, but also increased render time)",
- default=0.1,
- min=0.0000001, max=100000.0, soft_min=0.01, soft_max=1.0, precision=4
- )
+ volume_step_size: FloatProperty(
+ name="Step Size",
+ description="Distance between volume shader samples when rendering the volume "
+ "(lower values give more accurate and detailed results, but also increased render time)",
+ default=0.1,
+ min=0.0000001, max=100000.0, soft_min=0.01, soft_max=1.0, precision=4,
+ unit='LENGTH'
+ )
- cls.volume_max_steps = IntProperty(
- name="Max Steps",
- description="Maximum number of steps through the volume before giving up, "
- "to avoid extremely long render times with big objects or small step sizes",
- default=1024,
- min=2, max=65536
- )
+ volume_max_steps: IntProperty(
+ name="Max Steps",
+ description="Maximum number of steps through the volume before giving up, "
+ "to avoid extremely long render times with big objects or small step sizes",
+ default=1024,
+ min=2, max=65536
+ )
- cls.dicing_rate = FloatProperty(
- name="Dicing Rate",
- description="Size of a micropolygon in pixels",
- min=0.1, max=1000.0, soft_min=0.5,
- default=1.0,
- subtype="PIXEL"
- )
- cls.preview_dicing_rate = FloatProperty(
- name="Preview Dicing Rate",
- description="Size of a micropolygon in pixels during preview render",
- min=0.1, max=1000.0, soft_min=0.5,
- default=8.0,
- subtype="PIXEL"
- )
+ dicing_rate: FloatProperty(
+ name="Dicing Rate",
+ description="Size of a micropolygon in pixels",
+ min=0.1, max=1000.0, soft_min=0.5,
+ default=1.0,
+ subtype='PIXEL'
+ )
+ preview_dicing_rate: FloatProperty(
+ name="Preview Dicing Rate",
+ description="Size of a micropolygon in pixels during preview render",
+ min=0.1, max=1000.0, soft_min=0.5,
+ default=8.0,
+ subtype='PIXEL'
+ )
- cls.max_subdivisions = IntProperty(
- name="Max Subdivisions",
- description="Stop subdividing when this level is reached even if the dice rate would produce finer tessellation",
- min=0, max=16,
- default=12,
- )
+ max_subdivisions: IntProperty(
+ name="Max Subdivisions",
+ description="Stop subdividing when this level is reached even if the dice rate would produce finer tessellation",
+ min=0, max=16,
+ default=12,
+ )
- cls.dicing_camera = PointerProperty(
- name="Dicing Camera",
- description="Camera to use as reference point when subdividing geometry, useful to avoid crawling "
- "artifacts in animations when the scene camera is moving",
- type=bpy.types.Object,
- poll=lambda self, obj: obj.type == 'CAMERA',
- )
- cls.offscreen_dicing_scale = FloatProperty(
- name="Offscreen Dicing Scale",
- description="Multiplier for dicing rate of geometry outside of the camera view. The dicing rate "
- "of objects is gradually increased the further they are outside the camera view. "
- "Lower values provide higher quality reflections and shadows for off screen objects, "
- "while higher values use less memory",
- min=1.0, soft_max=25.0,
- default=4.0,
- )
+ dicing_camera: PointerProperty(
+ name="Dicing Camera",
+ description="Camera to use as reference point when subdividing geometry, useful to avoid crawling "
+ "artifacts in animations when the scene camera is moving",
+ type=bpy.types.Object,
+ poll=lambda self, obj: obj.type == 'CAMERA',
+ )
+ offscreen_dicing_scale: FloatProperty(
+ name="Offscreen Dicing Scale",
+ description="Multiplier for dicing rate of geometry outside of the camera view. The dicing rate "
+ "of objects is gradually increased the further they are outside the camera view. "
+ "Lower values provide higher quality reflections and shadows for off screen objects, "
+ "while higher values use less memory",
+ min=1.0, soft_max=25.0,
+ default=4.0,
+ )
- cls.film_exposure = FloatProperty(
- name="Exposure",
- description="Image brightness scale",
- min=0.0, max=10.0,
- default=1.0,
- )
- cls.film_transparent = BoolProperty(
- name="Transparent",
- description="World background is transparent, for compositing the render over another background",
- default=False,
- )
- cls.film_transparent_glass = BoolProperty(
- name="Transparent Glass",
- description="Render transmissive surfaces as transparent, for compositing glass over another background",
- default=False,
- )
- cls.film_transparent_roughness = FloatProperty(
- name="Transparent Roughness Threshold",
- description="For transparent transmission, keep surfaces with roughness above the threshold opaque",
- min=0.0, max=1.0,
- default=0.1,
- )
+ film_exposure: FloatProperty(
+ name="Exposure",
+ description="Image brightness scale",
+ min=0.0, max=10.0,
+ default=1.0,
+ )
+ film_transparent: BoolProperty(
+ name="Transparent",
+ description="World background is transparent, for compositing the render over another background",
+ default=False,
+ )
+ film_transparent_glass: BoolProperty(
+ name="Transparent Glass",
+ description="Render transmissive surfaces as transparent, for compositing glass over another background",
+ default=False,
+ )
+ film_transparent_roughness: FloatProperty(
+ name="Transparent Roughness Threshold",
+ description="For transparent transmission, keep surfaces with roughness above the threshold opaque",
+ min=0.0, max=1.0,
+ default=0.1,
+ )
- # Really annoyingly, we have to keep it around for a few releases,
- # otherwise forward compatibility breaks in really bad manner: CRASH!
- #
- # TODO(sergey): Remove this during 2.8x series of Blender.
- cls.filter_type = EnumProperty(
- name="Filter Type",
- description="Pixel filter type",
- items=enum_filter_types,
- default='BLACKMAN_HARRIS',
- )
+ # Really annoyingly, we have to keep it around for a few releases,
+ # otherwise forward compatibility breaks in really bad manner: CRASH!
+ #
+ # TODO(sergey): Remove this during 2.8x series of Blender.
+ filter_type: EnumProperty(
+ name="Filter Type",
+ description="Pixel filter type",
+ items=enum_filter_types,
+ default='BLACKMAN_HARRIS',
+ )
- cls.pixel_filter_type = EnumProperty(
- name="Filter Type",
- description="Pixel filter type",
- items=enum_filter_types,
- default='BLACKMAN_HARRIS',
- )
+ pixel_filter_type: EnumProperty(
+ name="Filter Type",
+ description="Pixel filter type",
+ items=enum_filter_types,
+ default='BLACKMAN_HARRIS',
+ )
- cls.filter_width = FloatProperty(
- name="Filter Width",
- description="Pixel filter width",
- min=0.01, max=10.0,
- default=1.5,
- )
+ filter_width: FloatProperty(
+ name="Filter Width",
+ description="Pixel filter width",
+ min=0.01, max=10.0,
+ default=1.5,
+ subtype='PIXEL'
+ )
- cls.seed = IntProperty(
- name="Seed",
- description="Seed value for integrator to get different noise patterns",
- min=0, max=2147483647,
- default=0,
- )
+ seed: IntProperty(
+ name="Seed",
+ description="Seed value for integrator to get different noise patterns",
+ min=0, max=2147483647,
+ default=0,
+ )
- cls.use_animated_seed = BoolProperty(
- name="Use Animated Seed",
- description="Use different seed values (and hence noise patterns) at different frames",
- default=False,
- )
+ use_animated_seed: BoolProperty(
+ name="Use Animated Seed",
+ description="Use different seed values (and hence noise patterns) at different frames",
+ default=False,
+ )
- cls.sample_clamp_direct = FloatProperty(
- name="Clamp Direct",
- description="If non-zero, the maximum value for a direct sample, "
- "higher values will be scaled down to avoid too "
- "much noise and slow convergence at the cost of accuracy",
- min=0.0, max=1e8,
- default=0.0,
- )
+ sample_clamp_direct: FloatProperty(
+ name="Clamp Direct",
+ description="If non-zero, the maximum value for a direct sample, "
+ "higher values will be scaled down to avoid too "
+ "much noise and slow convergence at the cost of accuracy",
+ min=0.0, max=1e8,
+ default=0.0,
+ )
- cls.sample_clamp_indirect = FloatProperty(
- name="Clamp Indirect",
- description="If non-zero, the maximum value for an indirect sample, "
- "higher values will be scaled down to avoid too "
- "much noise and slow convergence at the cost of accuracy",
- min=0.0, max=1e8,
- default=10.0,
- )
+ sample_clamp_indirect: FloatProperty(
+ name="Clamp Indirect",
+ description="If non-zero, the maximum value for an indirect sample, "
+ "higher values will be scaled down to avoid too "
+ "much noise and slow convergence at the cost of accuracy",
+ min=0.0, max=1e8,
+ default=10.0,
+ )
- cls.debug_tile_size = IntProperty(
- name="Tile Size",
- description="",
- min=1, max=4096,
- default=1024,
- )
+ debug_tile_size: IntProperty(
+ name="Tile Size",
+ description="",
+ min=1, max=4096,
+ default=1024,
+ )
- cls.preview_start_resolution = IntProperty(
- name="Start Resolution",
- description="Resolution to start rendering preview at, "
- "progressively increasing it to the full viewport size",
- min=8, max=16384,
- default=64,
- )
+ preview_start_resolution: IntProperty(
+ name="Start Resolution",
+ description="Resolution to start rendering preview at, "
+ "progressively increasing it to the full viewport size",
+ min=8, max=16384,
+ default=64,
+ subtype='PIXEL'
+ )
- cls.debug_reset_timeout = FloatProperty(
- name="Reset timeout",
- description="",
- min=0.01, max=10.0,
- default=0.1,
- )
- cls.debug_cancel_timeout = FloatProperty(
- name="Cancel timeout",
- description="",
- min=0.01, max=10.0,
- default=0.1,
- )
- cls.debug_text_timeout = FloatProperty(
- name="Text timeout",
- description="",
- min=0.01, max=10.0,
- default=1.0,
- )
+ debug_reset_timeout: FloatProperty(
+ name="Reset timeout",
+ description="",
+ min=0.01, max=10.0,
+ default=0.1,
+ )
+ debug_cancel_timeout: FloatProperty(
+ name="Cancel timeout",
+ description="",
+ min=0.01, max=10.0,
+ default=0.1,
+ )
+ debug_text_timeout: FloatProperty(
+ name="Text timeout",
+ description="",
+ min=0.01, max=10.0,
+ default=1.0,
+ )
- cls.debug_bvh_type = EnumProperty(
- name="Viewport BVH Type",
- description="Choose between faster updates, or faster render",
- items=enum_bvh_types,
- default='DYNAMIC_BVH',
- )
- cls.debug_use_spatial_splits = BoolProperty(
- name="Use Spatial Splits",
- description="Use BVH spatial splits: longer builder time, faster render",
- default=False,
- )
- cls.debug_use_hair_bvh = BoolProperty(
- name="Use Hair BVH",
- description="Use special type BVH optimized for hair (uses more ram but renders faster)",
- default=True,
- )
- cls.use_bvh_embree = BoolProperty(
- name="Use Embree",
- description="Use Embree as ray accelerator",
- default=False,
- )
- cls.debug_bvh_time_steps = IntProperty(
- name="BVH Time Steps",
- description="Split BVH primitives by this number of time steps to speed up render time in cost of memory",
- default=0,
- min=0, max=16,
- )
- cls.tile_order = EnumProperty(
- name="Tile Order",
- description="Tile order for rendering",
- items=enum_tile_order,
- default='HILBERT_SPIRAL',
- options=set(), # Not animatable!
- )
- cls.use_progressive_refine = BoolProperty(
- name="Progressive Refine",
- description="Instead of rendering each tile until it is finished, "
- "refine the whole image progressively "
- "(this renders somewhat slower, "
- "but time can be saved by manually stopping the render when the noise is low enough)",
- default=False,
- )
+ debug_bvh_type: EnumProperty(
+ name="Viewport BVH Type",
+ description="Choose between faster updates, or faster render",
+ items=enum_bvh_types,
+ default='DYNAMIC_BVH',
+ )
+ use_bvh_embree: BoolProperty(
+ name="Use Embree",
+ description="Use Embree as ray accelerator",
+ default=False,
+ )
+ debug_use_spatial_splits: BoolProperty(
+ name="Use Spatial Splits",
+ description="Use BVH spatial splits: longer builder time, faster render",
+ default=False,
+ )
+ debug_use_hair_bvh: BoolProperty(
+ name="Use Hair BVH",
+ description="Use special type BVH optimized for hair (uses more ram but renders faster)",
+ default=True,
+ )
+ debug_bvh_time_steps: IntProperty(
+ name="BVH Time Steps",
+ description="Split BVH primitives by this number of time steps to speed up render time in cost of memory",
+ default=0,
+ min=0, max=16,
+ )
+ tile_order: EnumProperty(
+ name="Tile Order",
+ description="Tile order for rendering",
+ items=enum_tile_order,
+ default='HILBERT_SPIRAL',
+ options=set(), # Not animatable!
+ )
+ use_progressive_refine: BoolProperty(
+ name="Progressive Refine",
+ description="Instead of rendering each tile until it is finished, "
+ "refine the whole image progressively "
+ "(this renders somewhat slower, "
+ "but time can be saved by manually stopping the render when the noise is low enough)",
+ default=False,
+ )
- cls.bake_type = EnumProperty(
- name="Bake Type",
- default='COMBINED',
- description="Type of pass to bake",
- items=(
- ('COMBINED', "Combined", ""),
- ('AO', "Ambient Occlusion", ""),
- ('SHADOW', "Shadow", ""),
- ('NORMAL', "Normal", ""),
- ('UV', "UV", ""),
- ('ROUGHNESS', "Roughness", ""),
- ('EMIT', "Emit", ""),
- ('ENVIRONMENT', "Environment", ""),
- ('DIFFUSE', "Diffuse", ""),
- ('GLOSSY', "Glossy", ""),
- ('TRANSMISSION', "Transmission", ""),
- ('SUBSURFACE', "Subsurface", ""),
- ),
- )
+ bake_type: EnumProperty(
+ name="Bake Type",
+ default='COMBINED',
+ description="Type of pass to bake",
+ items=(
+ ('COMBINED', "Combined", ""),
+ ('AO', "Ambient Occlusion", ""),
+ ('SHADOW', "Shadow", ""),
+ ('NORMAL', "Normal", ""),
+ ('UV', "UV", ""),
+ ('ROUGHNESS', "Roughness", ""),
+ ('EMIT', "Emit", ""),
+ ('ENVIRONMENT', "Environment", ""),
+ ('DIFFUSE', "Diffuse", ""),
+ ('GLOSSY', "Glossy", ""),
+ ('TRANSMISSION', "Transmission", ""),
+ ('SUBSURFACE', "Subsurface", ""),
+ ),
+ )
- cls.use_camera_cull = BoolProperty(
- name="Use Camera Cull",
- description="Allow objects to be culled based on the camera frustum",
- default=False,
- )
+ use_camera_cull: BoolProperty(
+ name="Use Camera Cull",
+ description="Allow objects to be culled based on the camera frustum",
+ default=False,
+ )
- cls.camera_cull_margin = FloatProperty(
- name="Camera Cull Margin",
- description="Margin for the camera space culling",
- default=0.1,
- min=0.0, max=5.0
- )
+ camera_cull_margin: FloatProperty(
+ name="Camera Cull Margin",
+ description="Margin for the camera space culling",
+ default=0.1,
+ min=0.0, max=5.0,
+ subtype='FACTOR'
+ )
- cls.use_distance_cull = BoolProperty(
- name="Use Distance Cull",
- description="Allow objects to be culled based on the distance from camera",
- default=False,
- )
+ use_distance_cull: BoolProperty(
+ name="Use Distance Cull",
+ description="Allow objects to be culled based on the distance from camera",
+ default=False,
+ )
- cls.distance_cull_margin = FloatProperty(
- name="Cull Distance",
- description="Cull objects which are further away from camera than this distance",
- default=50,
- min=0.0
- )
+ distance_cull_margin: FloatProperty(
+ name="Cull Distance",
+ description="Cull objects which are further away from camera than this distance",
+ default=50,
+ min=0.0,
+ unit='LENGTH'
+ )
- cls.motion_blur_position = EnumProperty(
- name="Motion Blur Position",
- default='CENTER',
- description="Offset for the shutter's time interval, allows to change the motion blur trails",
- items=(
- ('START', "Start on Frame", "The shutter opens at the current frame"),
- ('CENTER', "Center on Frame", "The shutter is open during the current frame"),
- ('END', "End on Frame", "The shutter closes at the current frame"),
- ),
- )
+ motion_blur_position: EnumProperty(
+ name="Motion Blur Position",
+ default='CENTER',
+ description="Offset for the shutter's time interval, allows to change the motion blur trails",
+ items=(
+ ('START', "Start on Frame", "The shutter opens at the current frame"),
+ ('CENTER', "Center on Frame", "The shutter is open during the current frame"),
+ ('END', "End on Frame", "The shutter closes at the current frame"),
+ ),
+ )
- cls.rolling_shutter_type = EnumProperty(
- name="Shutter Type",
- default='NONE',
- description="Type of rolling shutter effect matching CMOS-based cameras",
- items=(
- ('NONE', "None", "No rolling shutter effect used"),
- ('TOP', "Top-Bottom", "Sensor is being scanned from top to bottom")
- # TODO(seergey): Are there real cameras with different scanning direction?
- ),
- )
+ rolling_shutter_type: EnumProperty(
+ name="Shutter Type",
+ default='NONE',
+ description="Type of rolling shutter effect matching CMOS-based cameras",
+ items=(
+ ('NONE', "None", "No rolling shutter effect used"),
+ ('TOP', "Top-Bottom", "Sensor is being scanned from top to bottom")
+ # TODO(seergey): Are there real cameras with different scanning direction?
+ ),
+ )
- cls.rolling_shutter_duration = FloatProperty(
- name="Rolling Shutter Duration",
- description="Scanline \"exposure\" time for the rolling shutter effect",
- default=0.1,
- min=0.0, max=1.0,
- )
+ rolling_shutter_duration: FloatProperty(
+ name="Rolling Shutter Duration",
+ description="Scanline \"exposure\" time for the rolling shutter effect",
+ default=0.1,
+ min=0.0, max=1.0,
+ )
- cls.texture_limit = EnumProperty(
- name="Viewport Texture Limit",
- default='OFF',
- description="Limit texture size used by viewport rendering",
- items=enum_texture_limit
- )
+ texture_limit: EnumProperty(
+ name="Viewport Texture Limit",
+ default='OFF',
+ description="Limit texture size used by viewport rendering",
+ items=enum_texture_limit
+ )
- cls.texture_limit_render = EnumProperty(
- name="Render Texture Limit",
- default='OFF',
- description="Limit texture size used by final rendering",
- items=enum_texture_limit
- )
+ texture_limit_render: EnumProperty(
+ name="Render Texture Limit",
+ default='OFF',
+ description="Limit texture size used by final rendering",
+ items=enum_texture_limit
+ )
- cls.ao_bounces = IntProperty(
- name="AO Bounces",
- default=0,
- description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
- min=0, max=1024,
- )
+ ao_bounces: IntProperty(
+ name="AO Bounces",
+ default=0,
+ description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
+ min=0, max=1024,
+ )
- cls.ao_bounces_render = IntProperty(
- name="AO Bounces Render",
- default=0,
- description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
- min=0, max=1024,
- )
+ ao_bounces_render: IntProperty(
+ name="AO Bounces Render",
+ default=0,
+ description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
+ min=0, max=1024,
+ )
- # Various fine-tuning debug flags
-
- def devices_update_callback(self, context):
- import _cycles
- scene = context.scene.as_pointer()
- return _cycles.debug_flags_update(scene)
-
- cls.debug_use_cpu_avx2 = BoolProperty(name="AVX2", default=True)
- cls.debug_use_cpu_avx = BoolProperty(name="AVX", default=True)
- cls.debug_use_cpu_sse41 = BoolProperty(name="SSE41", default=True)
- cls.debug_use_cpu_sse3 = BoolProperty(name="SSE3", default=True)
- cls.debug_use_cpu_sse2 = BoolProperty(name="SSE2", default=True)
- cls.debug_bvh_layout = EnumProperty(
- name="BVH Layout",
- items=enum_bvh_layouts,
- default='BVH8',
- )
- cls.debug_use_cpu_split_kernel = BoolProperty(name="Split Kernel", default=False)
-
- cls.debug_use_cuda_adaptive_compile = BoolProperty(name="Adaptive Compile", default=False)
- cls.debug_use_cuda_split_kernel = BoolProperty(name="Split Kernel", default=False)
-
- cls.debug_opencl_kernel_type = EnumProperty(
- name="OpenCL Kernel Type",
- default='DEFAULT',
- items=(
- ('DEFAULT', "Default", ""),
- ('MEGA', "Mega", ""),
- ('SPLIT', "Split", ""),
- ),
- update=devices_update_callback
- )
+ # Various fine-tuning debug flags
- cls.debug_opencl_device_type = EnumProperty(
- name="OpenCL Device Type",
- default='ALL',
- items=(
- ('NONE', "None", ""),
- ('ALL', "All", ""),
- ('DEFAULT', "Default", ""),
- ('CPU', "CPU", ""),
- ('GPU', "GPU", ""),
- ('ACCELERATOR', "Accelerator", ""),
- ),
- update=devices_update_callback
- )
+ def _devices_update_callback(self, context):
+ import _cycles
+ scene = context.scene.as_pointer()
+ return _cycles.debug_flags_update(scene)
+
+ debug_use_cpu_avx2: BoolProperty(name="AVX2", default=True)
+ debug_use_cpu_avx: BoolProperty(name="AVX", default=True)
+ debug_use_cpu_sse41: BoolProperty(name="SSE41", default=True)
+ debug_use_cpu_sse3: BoolProperty(name="SSE3", default=True)
+ debug_use_cpu_sse2: BoolProperty(name="SSE2", default=True)
+ debug_bvh_layout: EnumProperty(
+ name="BVH Layout",
+ items=enum_bvh_layouts,
+ default='BVH8',
+ )
+ debug_use_cpu_split_kernel: BoolProperty(name="Split Kernel", default=False)
+
+ debug_use_cuda_adaptive_compile: BoolProperty(name="Adaptive Compile", default=False)
+ debug_use_cuda_split_kernel: BoolProperty(name="Split Kernel", default=False)
+
+ debug_opencl_kernel_type: EnumProperty(
+ name="OpenCL Kernel Type",
+ default='DEFAULT',
+ items=(
+ ('DEFAULT', "Default", ""),
+ ('MEGA', "Mega", ""),
+ ('SPLIT', "Split", ""),
+ ),
+ update=_devices_update_callback
+ )
- cls.debug_opencl_kernel_single_program = BoolProperty(
- name="Single Program",
- default=True,
- update=devices_update_callback,
- )
+ debug_opencl_device_type: EnumProperty(
+ name="OpenCL Device Type",
+ default='ALL',
+ items=(
+ ('NONE', "None", ""),
+ ('ALL', "All", ""),
+ ('DEFAULT', "Default", ""),
+ ('CPU', "CPU", ""),
+ ('GPU', "GPU", ""),
+ ('ACCELERATOR', "Accelerator", ""),
+ ),
+ update=_devices_update_callback
+ )
+
+ debug_opencl_kernel_single_program: BoolProperty(
+ name="Single Program",
+ default=True,
+ update=_devices_update_callback,
+ )
+ del _devices_update_callback
- cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
+ debug_use_opencl_debug: BoolProperty(name="Debug OpenCL", default=False)
- cls.debug_opencl_mem_limit = IntProperty(name="Memory limit", default=0,
- description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)")
+ debug_opencl_mem_limit: IntProperty(
+ name="Memory limit",
+ default=0,
+ description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)"
+ )
+
+ @classmethod
+ def register(cls):
+ bpy.types.Scene.cycles = PointerProperty(
+ name="Cycles Render Settings",
+ description="Cycles render settings",
+ type=cls,
+ )
@classmethod
def unregister(cls):
@@ -741,113 +750,153 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
class CyclesCameraSettings(bpy.types.PropertyGroup):
+
+ aperture_type: EnumProperty(
+ name="Aperture Type",
+ description="Use f-stop number or aperture radius",
+ items=enum_aperture_types,
+ default='RADIUS',
+ )
+ aperture_fstop: FloatProperty(
+ name="Aperture f-stop",
+ description="F-stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
+ min=0.0, soft_min=0.1, soft_max=64.0,
+ default=5.6,
+ step=10,
+ precision=1,
+ )
+ aperture_size: FloatProperty(
+ name="Aperture Size",
+ description="Radius of the aperture for depth of field (higher values give more defocus)",
+ min=0.0, soft_max=10.0,
+ default=0.0,
+ step=1,
+ precision=4,
+ subtype='DISTANCE',
+ )
+ aperture_blades: IntProperty(
+ name="Aperture Blades",
+ description="Number of blades in aperture for polygonal bokeh (at least 3)",
+ min=0, max=100,
+ default=0,
+ )
+ aperture_rotation: FloatProperty(
+ name="Aperture Rotation",
+ description="Rotation of blades in aperture",
+ soft_min=-pi, soft_max=pi,
+ subtype='ANGLE',
+ default=0,
+ )
+ aperture_ratio: FloatProperty(
+ name="Aperture Ratio",
+ description="Distortion to simulate anamorphic lens bokeh",
+ min=0.01, soft_min=1.0, soft_max=2.0,
+ default=1.0,
+ precision=4,
+ )
+ panorama_type: EnumProperty(
+ name="Panorama Type",
+ description="Distortion to use for the calculation",
+ items=enum_panorama_types,
+ default='FISHEYE_EQUISOLID',
+ )
+ fisheye_fov: FloatProperty(
+ name="Field of View",
+ description="Field of view for the fisheye lens",
+ min=0.1745, soft_max=2.0 * pi, max=10.0 * pi,
+ subtype='ANGLE',
+ default=pi,
+ )
+ fisheye_lens: FloatProperty(
+ name="Fisheye Lens",
+ description="Lens focal length (mm)",
+ min=0.01, soft_max=15.0, max=100.0,
+ default=10.5,
+ )
+ latitude_min: FloatProperty(
+ name="Min Latitude",
+ description="Minimum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * pi, max=0.5 * pi,
+ subtype='ANGLE',
+ default=-0.5 * pi,
+ )
+ latitude_max: FloatProperty(
+ name="Max Latitude",
+ description="Maximum latitude (vertical angle) for the equirectangular lens",
+ min=-0.5 * pi, max=0.5 * pi,
+ subtype='ANGLE',
+ default=0.5 * pi,
+ )
+ longitude_min: FloatProperty(
+ name="Min Longitude",
+ description="Minimum longitude (horizontal angle) for the equirectangular lens",
+ min=-pi, max=pi,
+ subtype='ANGLE',
+ default=-pi,
+ )
+ longitude_max: FloatProperty(
+ name="Max Longitude",
+ description="Maximum longitude (horizontal angle) for the equirectangular lens",
+ min=-pi, max=pi,
+ subtype='ANGLE',
+ default=pi,
+ )
+
@classmethod
def register(cls):
- import math
-
bpy.types.Camera.cycles = PointerProperty(
name="Cycles Camera Settings",
description="Cycles camera settings",
type=cls,
)
- cls.aperture_type = EnumProperty(
- name="Aperture Type",
- description="Use f-stop number or aperture radius",
- items=enum_aperture_types,
- default='RADIUS',
- )
- cls.aperture_fstop = FloatProperty(
- name="Aperture f-stop",
- description="F-stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
- min=0.0, soft_min=0.1, soft_max=64.0,
- default=5.6,
- step=10,
- precision=1,
- )
- cls.aperture_size = FloatProperty(
- name="Aperture Size",
- description="Radius of the aperture for depth of field (higher values give more defocus)",
- min=0.0, soft_max=10.0,
- default=0.0,
- step=1,
- precision=4,
- subtype='DISTANCE',
- )
- cls.aperture_blades = IntProperty(
- name="Aperture Blades",
- description="Number of blades in aperture for polygonal bokeh (at least 3)",
- min=0, max=100,
- default=0,
- )
- cls.aperture_rotation = FloatProperty(
- name="Aperture Rotation",
- description="Rotation of blades in aperture",
- soft_min=-math.pi, soft_max=math.pi,
- subtype='ANGLE',
- default=0,
- )
- cls.aperture_ratio = FloatProperty(
- name="Aperture Ratio",
- description="Distortion to simulate anamorphic lens bokeh",
- min=0.01, soft_min=1.0, soft_max=2.0,
- default=1.0,
- precision=4,
- )
- cls.panorama_type = EnumProperty(
- name="Panorama Type",
- description="Distortion to use for the calculation",
- items=enum_panorama_types,
- default='FISHEYE_EQUISOLID',
- )
- cls.fisheye_fov = FloatProperty(
- name="Field of View",
- description="Field of view for the fisheye lens",
- min=0.1745, soft_max=2.0 * math.pi, max=10.0 * math.pi,
- subtype='ANGLE',
- default=math.pi,
- )
- cls.fisheye_lens = FloatProperty(
- name="Fisheye Lens",
- description="Lens focal length (mm)",
- min=0.01, soft_max=15.0, max=100.0,
- default=10.5,
- )
- cls.latitude_min = FloatProperty(
- name="Min Latitude",
- description="Minimum latitude (vertical angle) for the equirectangular lens",
- min=-0.5 * math.pi, max=0.5 * math.pi,
- subtype='ANGLE',
- default=-0.5 * math.pi,
- )
- cls.latitude_max = FloatProperty(
- name="Max Latitude",
- description="Maximum latitude (vertical angle) for the equirectangular lens",
- min=-0.5 * math.pi, max=0.5 * math.pi,
- subtype='ANGLE',
- default=0.5 * math.pi,
- )
- cls.longitude_min = FloatProperty(
- name="Min Longitude",
- description="Minimum longitude (horizontal angle) for the equirectangular lens",
- min=-math.pi, max=math.pi,
- subtype='ANGLE',
- default=-math.pi,
- )
- cls.longitude_max = FloatProperty(
- name="Max Longitude",
- description="Maximum longitude (horizontal angle) for the equirectangular lens",
- min=-math.pi, max=math.pi,
- subtype='ANGLE',
- default=math.pi,
- )
-
@classmethod
def unregister(cls):
del bpy.types.Camera.cycles
class CyclesMaterialSettings(bpy.types.PropertyGroup):
+
+ sample_as_light: BoolProperty(
+ name="Multiple Importance Sample",
+ description="Use multiple importance sampling for this material, "
+ "disabling may reduce overall noise for large "
+ "objects that emit little light compared to other light sources",
+ default=True,
+ )
+ use_transparent_shadow: BoolProperty(
+ name="Transparent Shadows",
+ description="Use transparent shadows for this material if it contains a Transparent BSDF, "
+ "disabling will render faster but not give accurate shadows",
+ default=True,
+ )
+ homogeneous_volume: BoolProperty(
+ name="Homogeneous Volume",
+ description="When using volume rendering, assume volume has the same density everywhere "
+ "(not using any textures), for faster rendering",
+ default=False,
+ )
+ volume_sampling: EnumProperty(
+ name="Volume Sampling",
+ description="Sampling method to use for volumes",
+ items=enum_volume_sampling,
+ default='MULTIPLE_IMPORTANCE',
+ )
+
+ volume_interpolation: EnumProperty(
+ name="Volume Interpolation",
+ description="Interpolation method to use for smoke/fire volumes",
+ items=enum_volume_interpolation,
+ default='LINEAR',
+ )
+
+ displacement_method: EnumProperty(
+ name="Displacement Method",
+ description="Method to use for the displacement",
+ items=enum_displacement_methods,
+ default='BUMP',
+ )
+
@classmethod
def register(cls):
bpy.types.Material.cycles = PointerProperty(
@@ -855,95 +904,103 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
description="Cycles material settings",
type=cls,
)
- cls.sample_as_light = BoolProperty(
- name="Multiple Importance Sample",
- description="Use multiple importance sampling for this material, "
- "disabling may reduce overall noise for large "
- "objects that emit little light compared to other light sources",
- default=True,
- )
- cls.use_transparent_shadow = BoolProperty(
- name="Transparent Shadows",
- description="Use transparent shadows for this material if it contains a Transparent BSDF, "
- "disabling will render faster but not give accurate shadows",
- default=True,
- )
- cls.homogeneous_volume = BoolProperty(
- name="Homogeneous Volume",
- description="When using volume rendering, assume volume has the same density everywhere "
- "(not using any textures), for faster rendering",
- default=False,
- )
- cls.volume_sampling = EnumProperty(
- name="Volume Sampling",
- description="Sampling method to use for volumes",
- items=enum_volume_sampling,
- default='MULTIPLE_IMPORTANCE',
- )
-
- cls.volume_interpolation = EnumProperty(
- name="Volume Interpolation",
- description="Interpolation method to use for smoke/fire volumes",
- items=enum_volume_interpolation,
- default='LINEAR',
- )
-
- cls.displacement_method = EnumProperty(
- name="Displacement Method",
- description="Method to use for the displacement",
- items=enum_displacement_methods,
- default='BUMP',
- )
@classmethod
def unregister(cls):
del bpy.types.Material.cycles
-class CyclesLampSettings(bpy.types.PropertyGroup):
+class CyclesLightSettings(bpy.types.PropertyGroup):
+
+ cast_shadow: BoolProperty(
+ name="Cast Shadow",
+ description="Light casts shadows",
+ default=True,
+ )
+ samples: IntProperty(
+ name="Samples",
+ description="Number of light samples to render for each AA sample",
+ min=1, max=10000,
+ default=1,
+ )
+ max_bounces: IntProperty(
+ name="Max Bounces",
+ description="Maximum number of bounces the light will contribute to the render",
+ min=0, max=1024,
+ default=1024,
+ )
+ use_multiple_importance_sampling: BoolProperty(
+ name="Multiple Importance Sample",
+ description="Use multiple importance sampling for the light, "
+ "reduces noise for area lights and sharp glossy materials",
+ default=True,
+ )
+ is_portal: BoolProperty(
+ name="Is Portal",
+ description="Use this area light to guide sampling of the background, "
+ "note that this will make the light invisible",
+ default=False,
+ )
+
@classmethod
def register(cls):
- bpy.types.Lamp.cycles = PointerProperty(
- name="Cycles Lamp Settings",
- description="Cycles lamp settings",
+ bpy.types.Light.cycles = PointerProperty(
+ name="Cycles Light Settings",
+ description="Cycles light settings",
type=cls,
)
- cls.cast_shadow = BoolProperty(
- name="Cast Shadow",
- description="Lamp casts shadows",
- default=True,
- )
- cls.samples = IntProperty(
- name="Samples",
- description="Number of light samples to render for each AA sample",
- min=1, max=10000,
- default=1,
- )
- cls.max_bounces = IntProperty(
- name="Max Bounces",
- description="Maximum number of bounces the light will contribute to the render",
- min=0, max=1024,
- default=1024,
- )
- cls.use_multiple_importance_sampling = BoolProperty(
- name="Multiple Importance Sample",
- description="Use multiple importance sampling for the lamp, "
- "reduces noise for area lamps and sharp glossy materials",
- default=True,
- )
- cls.is_portal = BoolProperty(
- name="Is Portal",
- description="Use this area lamp to guide sampling of the background, "
- "note that this will make the lamp invisible",
- default=False,
- )
@classmethod
def unregister(cls):
- del bpy.types.Lamp.cycles
+ del bpy.types.Light.cycles
class CyclesWorldSettings(bpy.types.PropertyGroup):
+
+ sampling_method: EnumProperty(
+ name="Sampling method",
+ description="How to sample the background light",
+ items=enum_world_mis,
+ default='AUTOMATIC',
+ )
+ sample_map_resolution: IntProperty(
+ name="Map Resolution",
+ description="Importance map size is resolution x resolution/2; "
+ "higher values potentially produce less noise, at the cost of memory and speed",
+ min=4, max=8192,
+ default=1024,
+ )
+ samples: IntProperty(
+ name="Samples",
+ description="Number of light samples to render for each AA sample",
+ min=1, max=10000,
+ default=1,
+ )
+ max_bounces: IntProperty(
+ name="Max Bounces",
+ description="Maximum number of bounces the background light will contribute to the render",
+ min=0, max=1024,
+ default=1024,
+ )
+ homogeneous_volume: BoolProperty(
+ name="Homogeneous Volume",
+ description="When using volume rendering, assume volume has the same density everywhere"
+ "(not using any textures), for faster rendering",
+ default=False,
+ )
+ volume_sampling: EnumProperty(
+ name="Volume Sampling",
+ description="Sampling method to use for volumes",
+ items=enum_volume_sampling,
+ default='EQUIANGULAR',
+ )
+ volume_interpolation: EnumProperty(
+ name="Volume Interpolation",
+ description="Interpolation method to use for volumes",
+ items=enum_volume_interpolation,
+ default='LINEAR',
+ )
+
@classmethod
def register(cls):
bpy.types.World.cycles = PointerProperty(
@@ -951,50 +1008,6 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
description="Cycles world settings",
type=cls,
)
- cls.sampling_method = EnumProperty(
- name="Sampling method",
- description="How to sample the background light",
- items=enum_world_mis,
- default='AUTOMATIC',
- )
- cls.sample_map_resolution = IntProperty(
- name="Map Resolution",
- description="Importance map size is resolution x resolution/2; "
- "higher values potentially produce less noise, at the cost of memory and speed",
- min=4, max=8192,
- default=1024,
- )
- cls.samples = IntProperty(
- name="Samples",
- description="Number of light samples to render for each AA sample",
- min=1, max=10000,
- default=1,
- )
- cls.max_bounces = IntProperty(
- name="Max Bounces",
- description="Maximum number of bounces the background light will contribute to the render",
- min=0, max=1024,
- default=1024,
- )
- cls.homogeneous_volume = BoolProperty(
- name="Homogeneous Volume",
- description="When using volume rendering, assume volume has the same density everywhere"
- "(not using any textures), for faster rendering",
- default=False,
- )
- cls.volume_sampling = EnumProperty(
- name="Volume Sampling",
- description="Sampling method to use for volumes",
- items=enum_volume_sampling,
- default='EQUIANGULAR',
- )
-
- cls.volume_interpolation = EnumProperty(
- name="Volume Interpolation",
- description="Interpolation method to use for volumes",
- items=enum_volume_interpolation,
- default='LINEAR',
- )
@classmethod
def unregister(cls):
@@ -1002,6 +1015,38 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
class CyclesVisibilitySettings(bpy.types.PropertyGroup):
+
+ camera: BoolProperty(
+ name="Camera",
+ description="Object visibility for camera rays",
+ default=True,
+ )
+ diffuse: BoolProperty(
+ name="Diffuse",
+ description="Object visibility for diffuse reflection rays",
+ default=True,
+ )
+ glossy: BoolProperty(
+ name="Glossy",
+ description="Object visibility for glossy reflection rays",
+ default=True,
+ )
+ transmission: BoolProperty(
+ name="Transmission",
+ description="Object visibility for transmission rays",
+ default=True,
+ )
+ shadow: BoolProperty(
+ name="Shadow",
+ description="Object visibility for shadow rays",
+ default=True,
+ )
+ scatter: BoolProperty(
+ name="Volume Scatter",
+ description="Object visibility for volume scatter rays",
+ default=True,
+ )
+
@classmethod
def register(cls):
bpy.types.Object.cycles_visibility = PointerProperty(
@@ -1016,37 +1061,6 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup):
type=cls,
)
- cls.camera = BoolProperty(
- name="Camera",
- description="Object visibility for camera rays",
- default=True,
- )
- cls.diffuse = BoolProperty(
- name="Diffuse",
- description="Object visibility for diffuse reflection rays",
- default=True,
- )
- cls.glossy = BoolProperty(
- name="Glossy",
- description="Object visibility for glossy reflection rays",
- default=True,
- )
- cls.transmission = BoolProperty(
- name="Transmission",
- description="Object visibility for transmission rays",
- default=True,
- )
- cls.shadow = BoolProperty(
- name="Shadow",
- description="Object visibility for shadow rays",
- default=True,
- )
- cls.scatter = BoolProperty(
- name="Volume Scatter",
- description="Object visibility for volume scatter rays",
- default=True,
- )
-
@classmethod
def unregister(cls):
del bpy.types.Object.cycles_visibility
@@ -1080,70 +1094,71 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
class CyclesObjectSettings(bpy.types.PropertyGroup):
- @classmethod
- def register(cls):
- bpy.types.Object.cycles = PointerProperty(
- name="Cycles Object Settings",
- description="Cycles object settings",
- type=cls,
- )
- cls.use_motion_blur = BoolProperty(
- name="Use Motion Blur",
- description="Use motion blur for this object",
- default=True,
- )
+ use_motion_blur: BoolProperty(
+ name="Use Motion Blur",
+ description="Use motion blur for this object",
+ default=True,
+ )
- cls.use_deform_motion = BoolProperty(
- name="Use Deformation Motion",
- description="Use deformation motion blur for this object",
- default=True,
- )
+ use_deform_motion: BoolProperty(
+ name="Use Deformation Motion",
+ description="Use deformation motion blur for this object",
+ default=True,
+ )
- cls.motion_steps = IntProperty(
- name="Motion Steps",
- description="Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))",
- min=1, soft_max=8,
- default=1,
- )
+ motion_steps: IntProperty(
+ name="Motion Steps",
+ description="Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))",
+ min=1, soft_max=8,
+ default=1,
+ )
- cls.use_camera_cull = BoolProperty(
- name="Use Camera Cull",
- description="Allow this object and its duplicators to be culled by camera space culling",
- default=False,
- )
+ use_camera_cull: BoolProperty(
+ name="Use Camera Cull",
+ description="Allow this object and its duplicators to be culled by camera space culling",
+ default=False,
+ )
- cls.use_distance_cull = BoolProperty(
- name="Use Distance Cull",
- description="Allow this object and its duplicators to be culled by distance from camera",
- default=False,
- )
+ use_distance_cull: BoolProperty(
+ name="Use Distance Cull",
+ description="Allow this object and its duplicators to be culled by distance from camera",
+ default=False,
+ )
- cls.use_adaptive_subdivision = BoolProperty(
- name="Use Adaptive Subdivision",
- description="Use adaptive render time subdivision",
- default=False,
- )
+ use_adaptive_subdivision: BoolProperty(
+ name="Use Adaptive Subdivision",
+ description="Use adaptive render time subdivision",
+ default=False,
+ )
- cls.dicing_rate = FloatProperty(
- name="Dicing Scale",
- description="Multiplier for scene dicing rate (located in the Geometry Panel)",
- min=0.1, max=1000.0, soft_min=0.5,
- default=1.0,
- )
+ dicing_rate: FloatProperty(
+ name="Dicing Scale",
+ description="Multiplier for scene dicing rate (located in the Subdivision panel)",
+ min=0.1, max=1000.0, soft_min=0.5,
+ default=1.0,
+ )
- cls.is_shadow_catcher = BoolProperty(
- name="Shadow Catcher",
- description="Only render shadows on this object, for compositing renders into real footage",
- default=False,
- )
+ is_shadow_catcher: BoolProperty(
+ name="Shadow Catcher",
+ description="Only render shadows on this object, for compositing renders into real footage",
+ default=False,
+ )
+
+ is_holdout: BoolProperty(
+ name="Holdout",
+ description="Render objects as a holdout or matte, creating a "
+ "hole in the image with zero alpha, to fill out in "
+ "compositing with real footage or another render",
+ default=False,
+ )
- cls.is_holdout = BoolProperty(
- name="Holdout",
- description="Render objects as a holdout or matte, creating a "
- "hole in the image with zero alpha, to fill out in "
- "compositing with real footange or another render",
- default=False,
+ @classmethod
+ def register(cls):
+ bpy.types.Object.cycles = PointerProperty(
+ name="Cycles Object Settings",
+ description="Cycles object settings",
+ type=cls,
)
@classmethod
@@ -1152,6 +1167,56 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
+
+ primitive: EnumProperty(
+ name="Primitive",
+ description="Type of primitive used for hair rendering",
+ items=enum_curve_primitives,
+ default='LINE_SEGMENTS',
+ )
+ shape: EnumProperty(
+ name="Shape",
+ description="Form of hair",
+ items=enum_curve_shape,
+ default='THICK',
+ )
+ cull_backfacing: BoolProperty(
+ name="Cull Back-faces",
+ description="Do not test the back-face of each strand",
+ default=True,
+ )
+ use_curves: BoolProperty(
+ name="Use Cycles Hair Rendering",
+ description="Activate Cycles hair rendering for particle system",
+ default=True,
+ )
+ resolution: IntProperty(
+ name="Resolution",
+ description="Resolution of generated mesh",
+ min=3, max=64,
+ default=3,
+ )
+ minimum_width: FloatProperty(
+ name="Minimal width",
+ description="Minimal pixel width for strands (0 - deactivated)",
+ min=0.0, max=100.0,
+ default=0.0,
+ subtype='PIXEL'
+ )
+ maximum_width: FloatProperty(
+ name="Maximal width",
+ description="Maximum extension that strand radius can be increased by",
+ min=0.0, max=100.0,
+ default=0.1,
+ subtype='PIXEL'
+ )
+ subdivisions: IntProperty(
+ name="Subdivisions",
+ description="Number of subdivisions used in Cardinal curve intersection (power of 2)",
+ min=0, max=24,
+ default=4,
+ )
+
@classmethod
def register(cls):
bpy.types.Scene.cycles_curves = PointerProperty(
@@ -1159,52 +1224,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
description="Cycles hair rendering settings",
type=cls,
)
- cls.primitive = EnumProperty(
- name="Primitive",
- description="Type of primitive used for hair rendering",
- items=enum_curve_primitives,
- default='LINE_SEGMENTS',
- )
- cls.shape = EnumProperty(
- name="Shape",
- description="Form of hair",
- items=enum_curve_shape,
- default='THICK',
- )
- cls.cull_backfacing = BoolProperty(
- name="Cull back-faces",
- description="Do not test the back-face of each strand",
- default=True,
- )
- cls.use_curves = BoolProperty(
- name="Use Cycles Hair Rendering",
- description="Activate Cycles hair rendering for particle system",
- default=True,
- )
- cls.resolution = IntProperty(
- name="Resolution",
- description="Resolution of generated mesh",
- min=3, max=64,
- default=3,
- )
- cls.minimum_width = FloatProperty(
- name="Minimal width",
- description="Minimal pixel width for strands (0 - deactivated)",
- min=0.0, max=100.0,
- default=0.0,
- )
- cls.maximum_width = FloatProperty(
- name="Maximal width",
- description="Maximum extension that strand radius can be increased by",
- min=0.0, max=100.0,
- default=0.1,
- )
- cls.subdivisions = IntProperty(
- name="Subdivisions",
- description="Number of subdivisions used in Cardinal curve intersection (power of 2)",
- min=0, max=24,
- default=4,
- )
@classmethod
def unregister(cls):
@@ -1212,223 +1231,179 @@ 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",
- type=cls,
- )
- cls.pass_debug_bvh_traversed_nodes = BoolProperty(
- name="Debug BVH Traversed Nodes",
- description="Store Debug BVH Traversed Nodes pass",
- default=False,
- update=update_render_passes,
- )
- cls.pass_debug_bvh_traversed_instances = BoolProperty(
- name="Debug BVH Traversed Instances",
- description="Store Debug BVH Traversed Instances pass",
- default=False,
- update=update_render_passes,
- )
- cls.pass_debug_bvh_intersections = BoolProperty(
- name="Debug BVH Intersections",
- description="Store Debug BVH Intersections",
- default=False,
- update=update_render_passes,
- )
- cls.pass_debug_ray_bounces = BoolProperty(
- name="Debug Ray Bounces",
- description="Store Debug Ray Bounces pass",
- default=False,
- update=update_render_passes,
- )
- cls.pass_debug_render_time = BoolProperty(
- name="Debug Render Time",
- description="Render time in milliseconds per sample and pixel",
- default=False,
- update=update_render_passes,
- )
- cls.use_pass_volume_direct = BoolProperty(
- name="Volume Direct",
- description="Deliver direct volumetric scattering pass",
- default=False,
- update=update_render_passes,
- )
- cls.use_pass_volume_indirect = BoolProperty(
- name="Volume Indirect",
- description="Deliver indirect volumetric scattering pass",
- default=False,
- update=update_render_passes,
- )
- cls.use_denoising = BoolProperty(
- name="Use Denoising",
- description="Denoise the rendered image",
- default=False,
- update=update_render_passes,
- )
- cls.denoising_diffuse_direct = BoolProperty(
- name="Diffuse Direct",
- description="Denoise the direct diffuse lighting",
- default=True,
- )
- cls.denoising_diffuse_indirect = BoolProperty(
- name="Diffuse Indirect",
- description="Denoise the indirect diffuse lighting",
- default=True,
- )
- cls.denoising_glossy_direct = BoolProperty(
- name="Glossy Direct",
- description="Denoise the direct glossy lighting",
- default=True,
- )
- cls.denoising_glossy_indirect = BoolProperty(
- name="Glossy Indirect",
- description="Denoise the indirect glossy lighting",
- default=True,
- )
- cls.denoising_transmission_direct = BoolProperty(
- name="Transmission Direct",
- description="Denoise the direct transmission lighting",
- default=True,
- )
- cls.denoising_transmission_indirect = BoolProperty(
- name="Transmission Indirect",
- description="Denoise the indirect transmission lighting",
- default=True,
- )
- cls.denoising_subsurface_direct = BoolProperty(
- name="Subsurface Direct",
- description="Denoise the direct subsurface lighting",
- default=True,
- )
- cls.denoising_subsurface_indirect = BoolProperty(
- name="Subsurface Indirect",
- description="Denoise the indirect subsurface lighting",
- default=True,
- )
- cls.denoising_strength = FloatProperty(
- name="Denoising Strength",
- description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)",
- min=0.0, max=1.0,
- default=0.5,
- )
- cls.denoising_feature_strength = FloatProperty(
- name="Denoising Feature Strength",
- description="Controls removal of noisy image feature passes (lower values preserve more detail, but aren't as smooth)",
- min=0.0, max=1.0,
- default=0.5,
- )
- cls.denoising_radius = IntProperty(
- name="Denoising Radius",
- description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
- min=1, max=25,
- default=8,
- )
- cls.denoising_relative_pca = BoolProperty(
- name="Relative filter",
- description="When removing pixels that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
- default=False,
- )
- cls.denoising_store_passes = BoolProperty(
- name="Store denoising passes",
- description="Store the denoising feature passes and the noisy image",
- default=False,
- update=update_render_passes,
- )
- cls.use_pass_crypto_object = BoolProperty(
- name="Cryptomatte Object",
- description="Render cryptomatte object pass, for isolating objects in compositing",
- default=False,
- update=update_render_passes,
- )
- cls.use_pass_crypto_material = BoolProperty(
- name="Cryptomatte Material",
- description="Render cryptomatte material pass, for isolating materials in compositing",
- default=False,
- update=update_render_passes,
- )
- cls.use_pass_crypto_asset = BoolProperty(
- name="Cryptomatte Asset",
- description="Render cryptomatte asset pass, for isolating groups of objects with the same parent",
- default=False,
- update=update_render_passes,
- )
- cls.pass_crypto_depth = IntProperty(
- name="Cryptomatte Levels",
- description="Sets how many unique objects can be distinguished per pixel",
- default=6, min=2, max=16, step=2,
- update=update_render_passes,
- )
- cls.pass_crypto_accurate = BoolProperty(
- name="Cryptomatte Accurate",
- description="Gerenate a more accurate Cryptomatte pass. CPU only, may render slower and use more memory",
- default=True,
- update=update_render_passes,
- )
- @classmethod
- def unregister(cls):
- del bpy.types.SceneRenderLayer.cycles
+ pass_debug_bvh_traversed_nodes: BoolProperty(
+ name="Debug BVH Traversed Nodes",
+ description="Store Debug BVH Traversed Nodes pass",
+ default=False,
+ update=update_render_passes,
+ )
+ pass_debug_bvh_traversed_instances: BoolProperty(
+ name="Debug BVH Traversed Instances",
+ description="Store Debug BVH Traversed Instances pass",
+ default=False,
+ update=update_render_passes,
+ )
+ pass_debug_bvh_intersections: BoolProperty(
+ name="Debug BVH Intersections",
+ description="Store Debug BVH Intersections",
+ default=False,
+ update=update_render_passes,
+ )
+ pass_debug_ray_bounces: BoolProperty(
+ name="Debug Ray Bounces",
+ description="Store Debug Ray Bounces pass",
+ default=False,
+ update=update_render_passes,
+ )
+ pass_debug_render_time: BoolProperty(
+ name="Debug Render Time",
+ description="Render time in milliseconds per sample and pixel",
+ default=False,
+ update=update_render_passes,
+ )
+ use_pass_volume_direct: BoolProperty(
+ name="Volume Direct",
+ description="Deliver direct volumetric scattering pass",
+ default=False,
+ update=update_render_passes,
+ )
+ use_pass_volume_indirect: BoolProperty(
+ name="Volume Indirect",
+ description="Deliver indirect volumetric scattering pass",
+ default=False,
+ update=update_render_passes,
+ )
+ use_denoising: BoolProperty(
+ name="Use Denoising",
+ description="Denoise the rendered image",
+ default=False,
+ update=update_render_passes,
+ )
+ denoising_diffuse_direct: BoolProperty(
+ name="Diffuse Direct",
+ description="Denoise the direct diffuse lighting",
+ default=True,
+ )
+ denoising_diffuse_indirect: BoolProperty(
+ name="Diffuse Indirect",
+ description="Denoise the indirect diffuse lighting",
+ default=True,
+ )
+ denoising_glossy_direct: BoolProperty(
+ name="Glossy Direct",
+ description="Denoise the direct glossy lighting",
+ default=True,
+ )
+ denoising_glossy_indirect: BoolProperty(
+ name="Glossy Indirect",
+ description="Denoise the indirect glossy lighting",
+ default=True,
+ )
+ denoising_transmission_direct: BoolProperty(
+ name="Transmission Direct",
+ description="Denoise the direct transmission lighting",
+ default=True,
+ )
+ denoising_transmission_indirect: BoolProperty(
+ name="Transmission Indirect",
+ description="Denoise the indirect transmission lighting",
+ default=True,
+ )
+ denoising_subsurface_direct: BoolProperty(
+ name="Subsurface Direct",
+ description="Denoise the direct subsurface lighting",
+ default=True,
+ )
+ denoising_subsurface_indirect: BoolProperty(
+ name="Subsurface Indirect",
+ description="Denoise the indirect subsurface lighting",
+ default=True,
+ )
+ denoising_strength: FloatProperty(
+ name="Denoising Strength",
+ description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)",
+ min=0.0, max=1.0,
+ default=0.5,
+ )
+ denoising_feature_strength: FloatProperty(
+ name="Denoising Feature Strength",
+ description="Controls removal of noisy image feature passes (lower values preserve more detail, but aren't as smooth)",
+ min=0.0, max=1.0,
+ default=0.5,
+ )
+ denoising_radius: IntProperty(
+ name="Denoising Radius",
+ description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
+ min=1, max=25,
+ default=8,
+ )
+ denoising_relative_pca: BoolProperty(
+ name="Relative filter",
+ description="When removing pixels that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
+ default=False,
+ )
+ denoising_store_passes: BoolProperty(
+ name="Store denoising passes",
+ description="Store the denoising feature passes and the noisy image",
+ default=False,
+ update=update_render_passes,
+ )
+ use_pass_crypto_object: BoolProperty(
+ name="Cryptomatte Object",
+ description="Render cryptomatte object pass, for isolating objects in compositing",
+ default=False,
+ update=update_render_passes,
+ )
+ use_pass_crypto_material: BoolProperty(
+ name="Cryptomatte Material",
+ description="Render cryptomatte material pass, for isolating materials in compositing",
+ default=False,
+ update=update_render_passes,
+ )
+ use_pass_crypto_asset: BoolProperty(
+ name="Cryptomatte Asset",
+ description="Render cryptomatte asset pass, for isolating groups of objects with the same parent",
+ default=False,
+ update=update_render_passes,
+ )
+ pass_crypto_depth: IntProperty(
+ name="Cryptomatte Levels",
+ description="Sets how many unique objects can be distinguished per pixel",
+ default=6, min=2, max=16, step=2,
+ update=update_render_passes,
+ )
+ pass_crypto_accurate: BoolProperty(
+ name="Cryptomatte Accurate",
+ description="Generate a more accurate Cryptomatte pass. CPU only, may render slower and use more memory",
+ default=True,
+ update=update_render_passes,
+ )
-class CyclesCurveSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
- bpy.types.ParticleSettings.cycles = PointerProperty(
- name="Cycles Hair Settings",
- description="Cycles hair settings",
+ bpy.types.ViewLayer.cycles = PointerProperty(
+ name="Cycles ViewLayer Settings",
+ description="Cycles ViewLayer Settings",
type=cls,
)
- cls.radius_scale = FloatProperty(
- name="Radius Scaling",
- description="Multiplier of width properties",
- min=0.0, max=1000.0,
- default=0.01,
- )
- cls.root_width = FloatProperty(
- name="Root Size",
- description="Strand's width at root",
- min=0.0, max=1000.0,
- default=1.0,
- )
- cls.tip_width = FloatProperty(
- name="Tip Multiplier",
- description="Strand's width at tip",
- min=0.0, max=1000.0,
- default=0.0,
- )
- cls.shape = FloatProperty(
- name="Strand Shape",
- description="Strand shape parameter",
- min=-1.0, max=1.0,
- default=0.0,
- )
- cls.use_closetip = BoolProperty(
- name="Close tip",
- description="Set tip radius to zero",
- default=True,
- )
@classmethod
def unregister(cls):
- del bpy.types.ParticleSettings.cycles
+ del bpy.types.ViewLayer.cycles
class CyclesDeviceSettings(bpy.types.PropertyGroup):
- @classmethod
- def register(cls):
- cls.id = StringProperty(name="ID")
- cls.name = StringProperty(name="Name")
- cls.use = BoolProperty(name="Use", default=True)
- cls.type = EnumProperty(name="Type", items=enum_device_type, default='CUDA')
+ id: StringProperty(name="ID")
+ name: StringProperty(name="Name")
+ use: BoolProperty(name="Use", default=True)
+ type: EnumProperty(name="Type", items=enum_device_type, default='CUDA')
class CyclesPreferences(bpy.types.AddonPreferences):
@@ -1444,13 +1419,13 @@ class CyclesPreferences(bpy.types.AddonPreferences):
list.append(('OPENCL', "OpenCL", "Use OpenCL for GPU acceleration", 2))
return list
- compute_device_type = EnumProperty(
+ compute_device_type: EnumProperty(
name="Compute Device Type",
description="Device to use for computation (rendering with Cycles)",
items=get_device_types,
)
- devices = bpy.props.CollectionProperty(type=CyclesDeviceSettings)
+ devices: bpy.props.CollectionProperty(type=CyclesDeviceSettings)
def find_existing_device_entry(self, device):
for device_entry in self.devices:
@@ -1550,13 +1525,12 @@ def register():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
bpy.utils.register_class(CyclesMaterialSettings)
- bpy.utils.register_class(CyclesLampSettings)
+ bpy.utils.register_class(CyclesLightSettings)
bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesVisibilitySettings)
bpy.utils.register_class(CyclesMeshSettings)
bpy.utils.register_class(CyclesObjectSettings)
bpy.utils.register_class(CyclesCurveRenderSettings)
- bpy.utils.register_class(CyclesCurveSettings)
bpy.utils.register_class(CyclesDeviceSettings)
bpy.utils.register_class(CyclesPreferences)
bpy.utils.register_class(CyclesRenderLayerSettings)
@@ -1566,13 +1540,12 @@ def unregister():
bpy.utils.unregister_class(CyclesRenderSettings)
bpy.utils.unregister_class(CyclesCameraSettings)
bpy.utils.unregister_class(CyclesMaterialSettings)
- bpy.utils.unregister_class(CyclesLampSettings)
+ bpy.utils.unregister_class(CyclesLightSettings)
bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings)
bpy.utils.unregister_class(CyclesObjectSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)
bpy.utils.unregister_class(CyclesCurveRenderSettings)
- bpy.utils.unregister_class(CyclesCurveSettings)
bpy.utils.unregister_class(CyclesDeviceSettings)
bpy.utils.unregister_class(CyclesPreferences)
bpy.utils.unregister_class(CyclesRenderLayerSettings)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 2f1adfe4178..667547633b4 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -17,29 +17,30 @@
# <pep8 compliant>
import bpy
+from bpy_extras.node_utils import find_node_input
+from bl_operators.presets import PresetMenu
import _cycles
from bpy.types import (
Panel,
- Menu,
Operator,
)
-class CYCLES_MT_sampling_presets(Menu):
+class CYCLES_PT_sampling_presets(PresetMenu):
bl_label = "Sampling Presets"
preset_subdir = "cycles/sampling"
preset_operator = "script.execute_preset"
+ preset_add_operator = "render.cycles_sampling_preset_add"
COMPAT_ENGINES = {'CYCLES'}
- draw = Menu.draw_preset
-class CYCLES_MT_integrator_presets(Menu):
+class CYCLES_PT_integrator_presets(PresetMenu):
bl_label = "Integrator Presets"
preset_subdir = "cycles/integrator"
preset_operator = "script.execute_preset"
+ preset_add_operator = "render.cycles_integrator_preset_add"
COMPAT_ENGINES = {'CYCLES'}
- draw = Menu.draw_preset
class CyclesButtonsPanel:
@@ -50,12 +51,21 @@ 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
+
+
+class CyclesNodeButtonsPanel:
+ bl_space_type = "NODE_EDITOR"
+ bl_region_type = "UI"
+ COMPAT_ENGINES = {'CYCLES'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.engine in cls.COMPAT_ENGINES
def get_device_type(context):
- return context.user_preferences.addons[__package__].preferences.compute_device_type
+ return context.preferences.addons[__package__].preferences.compute_device_type
def use_cpu(context):
@@ -92,7 +102,7 @@ def show_device_active(context):
cscene = context.scene.cycles
if cscene.device != 'GPU':
return True
- return context.user_preferences.addons[__package__].preferences.has_active_device()
+ return context.preferences.addons[__package__].preferences.has_active_device()
def draw_samples_info(layout, context):
@@ -129,21 +139,23 @@ def draw_samples_info(layout, context):
if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
col = layout.column(align=True)
col.scale_y = 0.6
- col.label("Total Samples:")
+ col.label(text="Total Samples:")
col.separator()
if integrator == 'PATH':
- col.label("%s AA" % aa)
+ col.label(text="%s AA" % aa)
else:
- col.label("%s AA, %s Diffuse, %s Glossy, %s Transmission" %
+ col.label(text="%s AA, %s Diffuse, %s Glossy, %s Transmission" %
(aa, d * aa, g * aa, t * aa))
col.separator()
- col.label("%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
+ col.label(text="%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
(ao * aa, ml * aa, sss * aa, vol * aa))
class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
bl_label = "Sampling"
- bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header_preset(self, context):
+ CYCLES_PT_sampling_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
@@ -151,168 +163,298 @@ class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
- row = layout.row(align=True)
- row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
- row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
- row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- row = layout.row()
- sub = row.row()
- sub.prop(cscene, "progressive", text="")
- row.prop(cscene, "use_square_samples")
+ layout.prop(cscene, "progressive")
- split = layout.split()
+ if cscene.progressive == 'PATH' or use_branched_path(context) is False:
+ col = layout.column(align=True)
+ col.prop(cscene, "samples", text="Render")
+ col.prop(cscene, "preview_samples", text="Viewport")
- col = split.column()
- sub = col.column(align=True)
- sub.label("Settings:")
+ draw_samples_info(layout, context)
+ else:
+ col = layout.column(align=True)
+ col.prop(cscene, "aa_samples", text="Render")
+ col.prop(cscene, "preview_aa_samples", text="Viewport")
- seed_sub = sub.row(align=True)
- seed_sub.prop(cscene, "seed")
- seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
- sub.prop(cscene, "sample_clamp_direct")
- sub.prop(cscene, "sample_clamp_indirect")
- sub.prop(cscene, "light_sampling_threshold")
+class CYCLES_RENDER_PT_sampling_sub_samples(CyclesButtonsPanel, Panel):
+ bl_label = "Sub Samples"
+ bl_parent_id = "CYCLES_RENDER_PT_sampling"
- if cscene.progressive == 'PATH' or use_branched_path(context) is False:
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Samples:")
- sub.prop(cscene, "samples", text="Render")
- sub.prop(cscene, "preview_samples", text="Preview")
- else:
- sub.label(text="AA Samples:")
- sub.prop(cscene, "aa_samples", text="Render")
- sub.prop(cscene, "preview_aa_samples", text="Preview")
+ @classmethod
+ def poll(self, context):
+ scene = context.scene
+ cscene = scene.cycles
+ return cscene.progressive != 'PATH' and use_branched_path(context)
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Samples:")
- sub.prop(cscene, "diffuse_samples", text="Diffuse")
- sub.prop(cscene, "glossy_samples", text="Glossy")
- sub.prop(cscene, "transmission_samples", text="Transmission")
- sub.prop(cscene, "ao_samples", text="AO")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- subsub = sub.row(align=True)
- subsub.active = use_sample_all_lights(context)
- subsub.prop(cscene, "mesh_light_samples", text="Mesh Light")
+ scene = context.scene
+ cscene = scene.cycles
+
+ col = layout.column(align=True)
+ col.prop(cscene, "diffuse_samples", text="Diffuse")
+ col.prop(cscene, "glossy_samples", text="Glossy")
+ col.prop(cscene, "transmission_samples", text="Transmission")
+ col.prop(cscene, "ao_samples", text="AO")
+
+ sub = col.row(align=True)
+ sub.active = use_sample_all_lights(context)
+ sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
+ col.prop(cscene, "subsurface_samples", text="Subsurface")
+ col.prop(cscene, "volume_samples", text="Volume")
+
+ draw_samples_info(layout, context)
+
+
+class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
+ bl_label = "Advanced"
+ bl_parent_id = "CYCLES_RENDER_PT_sampling"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ cscene = scene.cycles
- sub.prop(cscene, "subsurface_samples", text="Subsurface")
- sub.prop(cscene, "volume_samples", text="Volume")
+ row = layout.row(align=True)
+ row.prop(cscene, "seed")
+ row.prop(cscene, "use_animated_seed", text="", icon='TIME')
+
+ layout.prop(cscene, "sampling_pattern", text="Pattern")
+
+ layout.prop(cscene, "use_square_samples")
+ layout.separator()
+
+ col = layout.column(align=True)
+ col.prop(cscene, "light_sampling_threshold", text="Light Threshold")
+
+ if cscene.progressive != 'PATH' and use_branched_path(context):
col = layout.column(align=True)
col.prop(cscene, "sample_all_lights_direct")
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:
+ for view_layer in scene.view_layers:
+ if view_layer.samples > 0:
layout.separator()
layout.row().prop(cscene, "use_layer_samples")
break
- draw_samples_info(layout, context)
+class CYCLES_RENDER_PT_sampling_total(CyclesButtonsPanel, Panel):
+ bl_label = "Total Samples"
+ bl_parent_id = "CYCLES_RENDER_PT_sampling"
+
+ @classmethod
+ def poll(self, context):
+ scene = context.scene
+ cscene = scene.cycles
+
+ if cscene.use_square_samples:
+ return True
+
+ return cscene.progressive != 'PATH' and use_branched_path(context)
+
+ def draw(self, context):
+ layout = self.layout
+ cscene = context.scene.cycles
+ integrator = cscene.progressive
+
+ # Calculate sample values
+ if integrator == 'PATH':
+ aa = cscene.samples
+ if cscene.use_square_samples:
+ aa = aa * aa
+ else:
+ aa = cscene.aa_samples
+ d = cscene.diffuse_samples
+ g = cscene.glossy_samples
+ t = cscene.transmission_samples
+ ao = cscene.ao_samples
+ ml = cscene.mesh_light_samples
+ sss = cscene.subsurface_samples
+ vol = cscene.volume_samples
+
+ if cscene.use_square_samples:
+ aa = aa * aa
+ d = d * d
+ g = g * g
+ t = t * t
+ ao = ao * ao
+ ml = ml * ml
+ sss = sss * sss
+ vol = vol * vol
+
+ col = layout.column(align=True)
+ col.scale_y = 0.6
+ if integrator == 'PATH':
+ col.label(text="%s AA" % aa)
+ else:
+ col.label(text="%s AA, %s Diffuse, %s Glossy, %s Transmission" %
+ (aa, d * aa, g * aa, t * aa))
+ col.separator()
+ col.label(text="%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
+ (ao * aa, ml * aa, sss * aa, vol * aa))
-class CYCLES_RENDER_PT_geometry(CyclesButtonsPanel, Panel):
- bl_label = "Geometry"
+
+class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):
+ bl_label = "Subdivision"
bl_options = {'DEFAULT_CLOSED'}
+ @classmethod
+ def poll(self, context):
+ return context.scene.cycles.feature_set == 'EXPERIMENTAL'
+
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
- ccscene = scene.cycles_curves
- row = layout.row()
- row.label("Volume Sampling:")
- row = layout.row()
- row.prop(cscene, "volume_step_size")
- row.prop(cscene, "volume_max_steps")
+ col = layout.column()
+ sub = col.column(align=True)
+ sub.prop(cscene, "dicing_rate", text="Dicing Rate Render")
+ sub.prop(cscene, "preview_dicing_rate", text="Preview")
- layout.separator()
+ col.separator()
- if cscene.feature_set == 'EXPERIMENTAL':
- layout.label("Subdivision Rate:")
- split = layout.split()
+ col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale")
+ col.prop(cscene, "max_subdivisions")
- col = split.column()
- sub = col.column(align=True)
- sub.prop(cscene, "dicing_rate", text="Render")
- sub.prop(cscene, "preview_dicing_rate", text="Preview")
+ col.prop(cscene, "dicing_camera")
- col = split.column()
- col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale")
- col.prop(cscene, "max_subdivisions")
- layout.prop(cscene, "dicing_camera")
+class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
+ bl_label = "Hair"
+ bl_options = {'DEFAULT_CLOSED'}
- layout.separator()
+ def draw_header(self, context):
+ layout = self.layout
+ scene = context.scene
+ ccscene = scene.cycles_curves
- layout.label("Hair:")
- layout.prop(ccscene, "use_curves", text="Use Hair")
- col = layout.column()
- col.active = ccscene.use_curves
+ layout.prop(ccscene, "use_curves", text="")
- col.prop(ccscene, "primitive", text="Primitive")
- col.prop(ccscene, "shape", text="Shape")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ ccscene = scene.cycles_curves
+
+ layout.active = ccscene.use_curves
+ col = layout.column()
+ col.prop(ccscene, "minimum_width", text="Min Pixels")
+ col.prop(ccscene, "maximum_width", text="Max Extension")
+ col.prop(ccscene, "shape", text="Shape")
if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
col.prop(ccscene, "cull_backfacing", text="Cull back-faces")
+ col.prop(ccscene, "primitive", text="Primitive")
if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
col.prop(ccscene, "resolution", text="Resolution")
elif ccscene.primitive == 'CURVE_SEGMENTS':
col.prop(ccscene, "subdivisions", text="Curve subdivisions")
- row = col.row()
- row.prop(ccscene, "minimum_width", text="Min Pixels")
- row.prop(ccscene, "maximum_width", text="Max Extension")
+
+class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):
+ bl_label = "Volumes"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ cscene = scene.cycles
+
+ col = layout.column()
+ col.prop(cscene, "volume_step_size", text="Step Size")
+ col.prop(cscene, "volume_max_steps", text="Max Steps")
class CYCLES_RENDER_PT_light_paths(CyclesButtonsPanel, Panel):
bl_label = "Light Paths"
bl_options = {'DEFAULT_CLOSED'}
+ def draw_header_preset(self, context):
+ CYCLES_PT_integrator_presets.draw_panel_header(self.layout)
+
+ def draw(self, context):
+ pass
+
+
+class CYCLES_RENDER_PT_light_paths_max_bounces(CyclesButtonsPanel, Panel):
+ bl_label = "Max Bounces"
+ bl_parent_id = "CYCLES_RENDER_PT_light_paths"
+
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
- row = layout.row(align=True)
- row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
- row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
- row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
+ col = layout.column(align=True)
+ col.prop(cscene, "max_bounces", text="Total")
- split = layout.split()
+ col = layout.column(align=True)
+ col.prop(cscene, "diffuse_bounces", text="Diffuse")
+ col.prop(cscene, "glossy_bounces", text="Glossy")
+ col.prop(cscene, "transparent_max_bounces", text="Transparency")
+ col.prop(cscene, "transmission_bounces", text="Transmission")
+ col.prop(cscene, "volume_bounces", text="Volume")
- col = split.column()
- sub = col.column(align=True)
- sub.label("Transparency:")
- sub.prop(cscene, "transparent_max_bounces", text="Max")
+class CYCLES_RENDER_PT_light_paths_clamping(CyclesButtonsPanel, Panel):
+ bl_label = "Clamping"
+ bl_parent_id = "CYCLES_RENDER_PT_light_paths"
- col.separator()
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- col.prop(cscene, "caustics_reflective")
- col.prop(cscene, "caustics_refractive")
- col.prop(cscene, "blur_glossy")
+ scene = context.scene
+ cscene = scene.cycles
- col = split.column()
+ col = layout.column(align=True)
+ col.prop(cscene, "sample_clamp_direct", text="Direct Light")
+ col.prop(cscene, "sample_clamp_indirect", text="Indirect Light")
- sub = col.column(align=True)
- sub.label(text="Bounces:")
- sub.prop(cscene, "max_bounces", text="Max")
- sub = col.column(align=True)
- sub.prop(cscene, "diffuse_bounces", text="Diffuse")
- sub.prop(cscene, "glossy_bounces", text="Glossy")
- sub.prop(cscene, "transmission_bounces", text="Transmission")
- sub.prop(cscene, "volume_bounces", text="Volume")
+class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
+ bl_label = "Caustics"
+ bl_parent_id = "CYCLES_RENDER_PT_light_paths"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ cscene = scene.cycles
+
+ col = layout.column()
+ col.prop(cscene, "blur_glossy")
+ col.prop(cscene, "caustics_reflective")
+ col.prop(cscene, "caustics_refractive")
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
@@ -326,6 +468,8 @@ class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
cscene = scene.cycles
@@ -335,9 +479,29 @@ class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(cscene, "motion_blur_position", text="Position")
col.prop(rd, "motion_blur_shutter")
+ col.separator()
+ col.prop(cscene, "rolling_shutter_type", text="Rolling Shutter")
+ sub = col.column()
+ sub.active = cscene.rolling_shutter_type != 'NONE'
+ sub.prop(cscene, "rolling_shutter_duration")
+
+
+class CYCLES_RENDER_PT_motion_blur_curve(CyclesButtonsPanel, Panel):
+ bl_label = "Shutter Curve"
+ bl_parent_id = "CYCLES_RENDER_PT_motion_blur"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ rd = scene.render
+ layout.active = rd.use_motion_blur
col = layout.column()
- col.label("Shutter curve:")
+
col.template_curve_mapping(rd, "motion_blur_shutter_curve")
col = layout.column(align=True)
@@ -349,40 +513,66 @@ class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
row.operator("render.shutter_curve_preset", icon='LINCURVE', text="").shape = 'LINE'
row.operator("render.shutter_curve_preset", icon='NOCURVE', text="").shape = 'MAX'
- col = layout.column()
- col.prop(cscene, "rolling_shutter_type")
- row = col.row()
- row.active = cscene.rolling_shutter_type != 'NONE'
- row.prop(cscene, "rolling_shutter_duration")
-
class CYCLES_RENDER_PT_film(CyclesButtonsPanel, Panel):
bl_label = "Film"
+ bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ scene = context.scene
+ cscene = scene.cycles
+
+ col = layout.column()
+ col.prop(cscene, "film_exposure")
+
+
+class CYCLES_RENDER_PT_film_transparency(CyclesButtonsPanel, Panel):
+ bl_label = "Transparency"
+ bl_parent_id = "CYCLES_RENDER_PT_film"
+
+ def draw_header(self, context):
+ layout = self.layout
scene = context.scene
cscene = scene.cycles
- split = layout.split()
+ layout.prop(cscene, "film_transparent", text="")
- col = split.column()
- col.prop(cscene, "film_exposure")
- col.separator()
- sub = col.column(align=True)
- sub.prop(cscene, "pixel_filter_type", text="")
- if cscene.pixel_filter_type != 'BOX':
- sub.prop(cscene, "filter_width", text="Width")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ scene = context.scene
+ cscene = scene.cycles
- col = split.column()
- col.prop(cscene, "film_transparent")
- sub = col.row()
- sub.prop(cscene, "film_transparent_glass", text="Transparent Glass")
- sub.active = cscene.film_transparent
- sub = col.row()
- sub.prop(cscene, "film_transparent_roughness", text="Roughness Threshold")
+ layout.active = cscene.film_transparent
+
+ col = layout.column()
+ col.prop(cscene, "film_transparent_glass", text="Transparent Glass")
+
+ sub = col.column()
sub.active = cscene.film_transparent and cscene.film_transparent_glass
+ sub.prop(cscene, "film_transparent_roughness", text="Roughness Threshold")
+
+
+class CYCLES_RENDER_PT_film_pixel_filter(CyclesButtonsPanel, Panel):
+ bl_label = "Pixel Filter"
+ bl_parent_id = "CYCLES_RENDER_PT_film"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ scene = context.scene
+ cscene = scene.cycles
+
+ col = layout.column()
+ col.prop(cscene, "pixel_filter_type", text="Type")
+ if cscene.pixel_filter_type != 'BOX':
+ col.prop(cscene, "filter_width", text="Width")
class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
@@ -390,320 +580,432 @@ class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
+ pass
+
+
+class CYCLES_RENDER_PT_performance_threads(CyclesButtonsPanel, Panel):
+ bl_label = "Threads"
+ bl_parent_id = "CYCLES_RENDER_PT_performance"
+
+ def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
rd = scene.render
- cscene = scene.cycles
- split = layout.split()
-
- col = split.column(align=True)
+ col = layout.column()
- col.label(text="Threads:")
- col.row(align=True).prop(rd, "threads_mode", expand=True)
+ col.prop(rd, "threads_mode")
sub = col.column(align=True)
sub.enabled = rd.threads_mode == 'FIXED'
sub.prop(rd, "threads")
- col.separator()
- sub = col.column(align=True)
- sub.label(text="Tiles:")
- sub.prop(cscene, "tile_order", text="")
+class CYCLES_RENDER_PT_performance_tiles(CyclesButtonsPanel, Panel):
+ bl_label = "Tiles"
+ bl_parent_id = "CYCLES_RENDER_PT_performance"
- sub.prop(rd, "tile_x", text="X")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ rd = scene.render
+ cscene = scene.cycles
+
+ col = layout.column()
+
+ sub = col.column(align=True)
+ sub.prop(rd, "tile_x", text="Tiles X")
sub.prop(rd, "tile_y", text="Y")
+ col.prop(cscene, "tile_order", text="Order")
- subsub = sub.column()
- subsub.active = not rd.use_save_buffers
- for rl in rd.layers:
- if rl.cycles.use_denoising:
- subsub.active = False
- subsub.prop(cscene, "use_progressive_refine")
+ sub = col.column()
+ sub.active = not rd.use_save_buffers
+ for view_layer in scene.view_layers:
+ if view_layer.cycles.use_denoising:
+ sub.active = False
+ sub.prop(cscene, "use_progressive_refine")
- col = split.column()
- col.label(text="Final Render:")
- col.prop(rd, "use_save_buffers")
- col.prop(rd, "use_persistent_data", text="Persistent Images")
+class CYCLES_RENDER_PT_performance_acceleration_structure(CyclesButtonsPanel, Panel):
+ bl_label = "Acceleration Structure"
+ bl_parent_id = "CYCLES_RENDER_PT_performance"
- col.separator()
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ cscene = scene.cycles
+
+ col = layout.column()
- col.label(text="Acceleration structure:")
if _cycles.with_embree:
row = col.row()
row.active = use_cpu(context)
row.prop(cscene, "use_bvh_embree")
- row = col.row()
col.prop(cscene, "debug_use_spatial_splits")
- row = col.row()
- row.active = not cscene.use_bvh_embree or not _cycles.with_embree
- row.prop(cscene, "debug_use_hair_bvh")
+ sub = col.column()
+ sub.active = not cscene.use_bvh_embree or not _cycles.with_embree
+ sub.prop(cscene, "debug_use_hair_bvh")
+ sub = col.column()
+ sub.active = not cscene.debug_use_spatial_splits and not cscene.use_bvh_embree
+ sub.prop(cscene, "debug_bvh_time_steps")
+
+
+class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
+ bl_label = "Final Render"
+ bl_parent_id = "CYCLES_RENDER_PT_performance"
- row = col.row()
- row.active = not cscene.debug_use_spatial_splits and not cscene.use_bvh_embree
- row.prop(cscene, "debug_bvh_time_steps")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ rd = scene.render
col = layout.column()
- col.label(text="Viewport Resolution:")
- split = col.split()
- split.prop(rd, "preview_pixel_size", text="")
- split.prop(cscene, "preview_start_resolution")
+ col.prop(rd, "use_save_buffers")
+ col.prop(rd, "use_persistent_data", text="Persistent Images")
-class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel):
- bl_label = "Layer"
- bl_context = "render_layer"
+
+class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel):
+ bl_label = "Viewport"
+ bl_parent_id = "CYCLES_RENDER_PT_performance"
def draw(self, context):
layout = self.layout
- with_freestyle = bpy.app.build_options.freestyle
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
rd = scene.render
- rl = rd.layers.active
+ cscene = scene.cycles
- split = layout.split()
+ col = layout.column()
+ col.prop(rd, "preview_pixel_size", text="Pixel Size")
+ col.prop(cscene, "preview_start_resolution", text="Start Pixels")
- 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")
+class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
+ bl_label = "Filter"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_context = "view_layer"
- split = layout.split()
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- col = split.column()
- col.label(text="Material:")
- col.prop(rl, "material_override", text="")
- col.separator()
- col.prop(rl, "samples")
+ with_freestyle = bpy.app.build_options.freestyle
- 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")
+ scene = context.scene
+ rd = scene.render
+ view_layer = context.view_layer
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = flow.column()
+ col.prop(view_layer, "use_sky", text="Environment")
+ col = flow.column()
+ col.prop(view_layer, "use_ao", text="Ambient Occlusion")
+ col = flow.column()
+ col.prop(view_layer, "use_solid", text="Surfaces")
+ col = flow.column()
+ col.prop(view_layer, "use_strand", text="Hair")
if with_freestyle:
- row = col.row()
- row.prop(rl, "use_freestyle", "Use Freestyle")
- row.active = rd.use_freestyle
+ col = flow.column()
+ col.prop(view_layer, "use_freestyle", text="Freestyle")
+ col.active = rd.use_freestyle
+
+
+class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel):
+ bl_label = "Override"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_context = "view_layer"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ view_layer = context.view_layer
+
+ layout.prop(view_layer, "material_override")
+ layout.prop(view_layer, "samples")
-class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
+class CYCLES_RENDER_PT_passes(CyclesButtonsPanel, Panel):
bl_label = "Passes"
- bl_context = "render_layer"
+ bl_context = "view_layer"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
+ pass
+
+
+class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel):
+ bl_label = "Data"
+ bl_context = "view_layer"
+ bl_parent_id = "CYCLES_RENDER_PT_passes"
+
+ def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
rd = scene.render
- rl = rd.layers.active
- crl = rl.cycles
+ view_layer = context.view_layer
+ cycles_view_layer = view_layer.cycles
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ col = flow.column()
+ col.prop(view_layer, "use_pass_combined")
+ col = flow.column()
+ col.prop(view_layer, "use_pass_z")
+ col = flow.column()
+ col.prop(view_layer, "use_pass_mist")
+ col = flow.column()
+ col.prop(view_layer, "use_pass_normal")
+ col = flow.column()
+ col.prop(view_layer, "use_pass_vector")
+ col.active = not rd.use_motion_blur
+ col = flow.column()
+ col.prop(view_layer, "use_pass_uv")
+ col = flow.column()
+ col.prop(view_layer, "use_pass_object_index")
+ col = flow.column()
+ col.prop(view_layer, "use_pass_material_index")
- split = layout.split()
+ layout.separator()
- 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")
- row = col.row()
- row.prop(rl, "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.separator()
- col.prop(rl, "use_pass_shadow")
- col.prop(rl, "use_pass_ambient_occlusion")
- col.separator()
- col.prop(crl, "denoising_store_passes", text="Denoising Data")
- col.separator()
- col.prop(rl, "pass_alpha_threshold")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ col = flow.column()
+ col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
+ col = flow.column()
+ col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time")
- 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)
- 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)
- 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)
- 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)
- 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)
+ layout.separator()
- col.separator()
- col.prop(rl, "use_pass_emit", text="Emission")
- col.prop(rl, "use_pass_environment")
+ layout.prop(view_layer, "pass_alpha_threshold")
- col = layout.column()
- col.prop(crl, "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")
-
- crl = rl.cycles
- layout.label("Cryptomatte:")
- row = layout.row(align=True)
- row.prop(crl, "use_pass_crypto_object", text="Object", toggle=True)
- row.prop(crl, "use_pass_crypto_material", text="Material", toggle=True)
- row.prop(crl, "use_pass_crypto_asset", text="Asset", toggle=True)
- row = layout.row(align=True)
- row.prop(crl, "pass_crypto_depth")
- row = layout.row(align=True)
- row.active = use_cpu(context)
- row.prop(crl, "pass_crypto_accurate", text="Accurate Mode")
-class CYCLES_RENDER_PT_views(CyclesButtonsPanel, Panel):
- bl_label = "Views"
- bl_context = "render_layer"
- bl_options = {'DEFAULT_CLOSED'}
+class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel):
+ bl_label = "Light"
+ bl_context = "view_layer"
+ bl_parent_id = "CYCLES_RENDER_PT_passes"
- def draw_header(self, context):
- rd = context.scene.render
- self.layout.prop(rd, "use_multiview", text="")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ view_layer = context.view_layer
+ cycles_view_layer = view_layer.cycles
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Diffuse")
+ row = split.row(align=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)
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Glossy")
+ row = split.row(align=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)
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Transmission")
+ row = split.row(align=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)
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Subsurface")
+ row = split.row(align=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)
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Volume")
+ row = split.row(align=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 = layout.column(align=True)
+ col.prop(view_layer, "use_pass_emit", text="Emission")
+ col.prop(view_layer, "use_pass_environment")
+ col.prop(view_layer, "use_pass_shadow")
+ col.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion")
+
+
+class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel):
+ bl_label = "Cryptomatte"
+ bl_context = "view_layer"
+ bl_parent_id = "CYCLES_RENDER_PT_passes"
def draw(self, context):
+ import _cycles
+
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- scene = context.scene
- rd = scene.render
- rv = rd.views.active
+ cycles_view_layer = context.view_layer.cycles
- layout.active = rd.use_multiview
- basic_stereo = (rd.views_format == 'STEREO_3D')
+ row = layout.row(align=True)
+ row.use_property_split = False
+ row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True)
+ row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True)
+ row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True)
- row = layout.row()
- row.prop(rd, "views_format", expand=True)
+ layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels")
- 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(align=True)
+ row.active = use_cpu(context)
+ row.prop(cycles_view_layer, "pass_crypto_accurate", text="Accurate Mode")
- 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)
+class CYCLES_RENDER_PT_passes_debug(CyclesButtonsPanel, Panel):
+ bl_label = "Debug"
+ bl_context = "view_layer"
+ bl_parent_id = "CYCLES_RENDER_PT_passes"
- col = row.column(align=True)
- col.operator("scene.render_view_add", icon='ZOOMIN', text="")
- col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
+ @classmethod
+ def poll(cls, context):
+ import _cycles
+ return _cycles.with_cycles_debug
- row = layout.row()
- row.label(text="Camera Suffix:")
- row.prop(rv, "camera_suffix", text="")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ cycles_view_layer = context.view_layer.cycles
+
+ layout.prop(cycles_view_layer, "pass_debug_bvh_traversed_nodes")
+ layout.prop(cycles_view_layer, "pass_debug_bvh_traversed_instances")
+ layout.prop(cycles_view_layer, "pass_debug_bvh_intersections")
+ layout.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
layout = self.layout
- layout.prop(crl, "use_denoising", text="")
+ layout.prop(cycles_view_layer, "use_denoising", text="")
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
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
split = layout.split()
- split.active = crl.use_denoising
+ split.active = cycles_view_layer.use_denoising
+
+ layout = layout.column(align=True)
+ layout.prop(cycles_view_layer, "denoising_radius", text="Radius")
+ layout.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength")
+ layout.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
+ layout.prop(cycles_view_layer, "denoising_relative_pca")
+
+ layout.separator()
+
+ split = layout.split(factor=0.5)
+ split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
col = split.column()
- sub = col.column(align=True)
- sub.prop(crl, "denoising_radius", text="Radius")
- sub.prop(crl, "denoising_strength", slider=True, text="Strength")
+ col.alignment = 'RIGHT'
+ col.label(text="Diffuse")
+
+ row = split.row(align=True)
+ row.use_property_split = False
+ row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True)
+ row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True)
+
+ split = layout.split(factor=0.5)
+ split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
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")
+ col.alignment = 'RIGHT'
+ col.label(text="Glossy")
- layout.separator()
+ row = split.row(align=True)
+ row.use_property_split = False
+ row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True)
+ row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True)
- row = layout.row()
- row.active = crl.use_denoising or crl.denoising_store_passes
- 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)
+ split = layout.split(factor=0.5)
+ split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
- row = layout.row()
- row.active = crl.use_denoising or crl.denoising_store_passes
- 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)
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Transmission")
- row = layout.row()
- row.active = crl.use_denoising or crl.denoising_store_passes
- 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)
+ row = split.row(align=True)
+ row.use_property_split = False
+ row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True)
+ row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True)
- row = layout.row()
- row.active = crl.use_denoising or crl.denoising_store_passes
- 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)
+ split = layout.split(factor=0.5)
+ split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
+
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Subsurface")
+
+ row = split.row(align=True)
+ row.use_property_split = False
+ row.prop(cycles_view_layer, "denoising_subsurface_direct", text="Direct", toggle=True)
+ row.prop(cycles_view_layer, "denoising_subsurface_indirect", text="Indirect", toggle=True)
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
+ bl_context = "output"
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
rd = context.scene.render
- split = layout.split()
-
- col = split.column()
+ col = layout.column(align=True)
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
- col = split.column()
- col.prop(rd, "dither_intensity", text="Dither", slider=True)
+ layout.prop(rd, "dither_intensity", text="Dither", slider=True)
class CYCLES_CAMERA_PT_dof(CyclesButtonsPanel, Panel):
@@ -716,45 +1018,69 @@ class CYCLES_CAMERA_PT_dof(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
cam = context.camera
- ccam = cam.cycles
- dof_options = cam.gpu_dof
split = layout.split()
col = split.column()
- col.label("Focus:")
- col.prop(cam, "dof_object", text="")
+ col.prop(cam, "dof_object", text="Focus Object")
sub = col.row()
sub.active = cam.dof_object is None
sub.prop(cam, "dof_distance", text="Distance")
- hq_support = dof_options.is_hq_supported
- sub = col.column(align=True)
- sub.label("Viewport:")
- subhq = sub.column()
- subhq.active = hq_support
- subhq.prop(dof_options, "use_high_quality")
- sub.prop(dof_options, "fstop")
- if dof_options.use_high_quality and hq_support:
- sub.prop(dof_options, "blades")
- col = split.column()
+class CYCLES_CAMERA_PT_dof_aperture(CyclesButtonsPanel, Panel):
+ bl_label = "Aperture"
+ bl_parent_id = "CYCLES_CAMERA_PT_dof"
- col.label("Aperture:")
- sub = col.column(align=True)
- sub.prop(ccam, "aperture_type", text="")
+ @classmethod
+ def poll(cls, context):
+ return context.camera and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ cam = context.camera
+ ccam = cam.cycles
+
+ col = flow.column()
+ col.prop(ccam, "aperture_type")
if ccam.aperture_type == 'RADIUS':
- sub.prop(ccam, "aperture_size", text="Size")
+ col.prop(ccam, "aperture_size", text="Size")
elif ccam.aperture_type == 'FSTOP':
- sub.prop(ccam, "aperture_fstop", text="Number")
+ col.prop(ccam, "aperture_fstop", text="Number")
+ col.separator()
+
+ col = flow.column()
+ col.prop(ccam, "aperture_blades", text="Blades")
+ col.prop(ccam, "aperture_rotation", text="Rotation")
+ col.prop(ccam, "aperture_ratio", text="Ratio")
- sub = col.column(align=True)
- sub.prop(ccam, "aperture_blades", text="Blades")
- sub.prop(ccam, "aperture_rotation", text="Rotation")
- sub.prop(ccam, "aperture_ratio", text="Ratio")
+
+class CYCLES_CAMERA_PT_dof_viewport(CyclesButtonsPanel, Panel):
+ bl_label = "Viewport"
+ bl_parent_id = "CYCLES_CAMERA_PT_dof"
+
+ @classmethod
+ def poll(cls, context):
+ return context.camera and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ cam = context.camera
+ dof_options = cam.gpu_dof
+
+ sub = flow.column(align=True)
+ sub.prop(dof_options, "fstop")
+ sub.prop(dof_options, "blades")
class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
@@ -764,7 +1090,10 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- return (context.material or context.object) and CyclesButtonsPanel.poll(context)
+ if context.active_object and context.active_object.type == 'GPENCIL':
+ return False
+ else:
+ return (context.material or context.object) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -785,8 +1114,8 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
col = row.column(align=True)
- col.operator("object.material_slot_add", icon='ZOOMIN', text="")
- col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
+ col.operator("object.material_slot_add", icon='ADD', text="")
+ col.operator("object.material_slot_remove", icon='REMOVE', text="")
col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
@@ -802,7 +1131,7 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
row.operator("object.material_slot_select", text="Select")
row.operator("object.material_slot_deselect", text="Deselect")
- split = layout.split(percentage=0.65)
+ split = layout.split(factor=0.65)
if ob:
split.template_ID(ob, "active_material", new="material.new")
@@ -828,7 +1157,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
if CyclesButtonsPanel.poll(context) and ob:
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}:
return True
- if ob.dupli_type == 'GROUP' and ob.dupli_group:
+ if ob.instance_type == 'COLLECTION' and ob.instance_collection:
return True
# TODO(sergey): More duplicator types here?
return False
@@ -872,91 +1201,103 @@ class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel):
def poll(cls, context):
ob = context.object
return (CyclesButtonsPanel.poll(context) and
- ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
- (ob.dupli_type == 'GROUP' and ob.dupli_group)))
+ ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or
+ (ob.instance_type == 'COLLECTION' and ob.instance_collection)))
+
+ def draw(self, context):
+ pass
+
+
+class CYCLES_OBJECT_PT_cycles_settings_ray_visibility(CyclesButtonsPanel, Panel):
+ bl_label = "Ray Visibility"
+ bl_parent_id = "CYCLES_OBJECT_PT_cycles_settings"
+ bl_context = "object"
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
- cscene = scene.cycles
ob = context.object
cob = ob.cycles
visibility = ob.cycles_visibility
- layout.label(text="Ray Visibility:")
- flow = layout.column_flow()
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- flow.prop(visibility, "camera")
- flow.prop(visibility, "diffuse")
- flow.prop(visibility, "glossy")
- flow.prop(visibility, "transmission")
- flow.prop(visibility, "scatter")
+ col = flow.column()
+ col.prop(visibility, "camera")
+ col = flow.column()
+ col.prop(visibility, "diffuse")
+ col = flow.column()
+ col.prop(visibility, "glossy")
+ col = flow.column()
+ col.prop(visibility, "transmission")
+ col = flow.column()
+ col.prop(visibility, "scatter")
- if ob.type != 'LAMP':
- flow.prop(visibility, "shadow")
+ if ob.type != 'LIGHT':
+ col = flow.column()
+ col.prop(visibility, "shadow")
- row = layout.row()
- row.prop(cob, "is_shadow_catcher")
- row.prop(cob, "is_holdout")
+ layout.separator()
- col = layout.column()
- col.label(text="Performance:")
- row = col.row()
- sub = row.row()
- sub.active = scene.render.use_simplify and cscene.use_camera_cull
- sub.prop(cob, "use_camera_cull")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = flow.column()
+ col.prop(cob, "is_shadow_catcher")
+ col = flow.column()
+ col.prop(cob, "is_holdout")
+
+
+class CYCLES_OBJECT_PT_cycles_settings_performance(CyclesButtonsPanel, Panel):
+ bl_label = "Performance"
+ bl_parent_id = "CYCLES_OBJECT_PT_cycles_settings"
+ bl_context = "object"
+
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ cscene = scene.cycles
+ ob = context.object
+ cob = ob.cycles
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = flow.column()
+ col.active = scene.render.use_simplify and cscene.use_camera_cull
+ col.prop(cob, "use_camera_cull")
- sub = row.row()
- sub.active = scene.render.use_simplify and cscene.use_distance_cull
- sub.prop(cob, "use_distance_cull")
+ col = flow.column()
+ col.active = scene.render.use_simplify and cscene.use_distance_cull
+ col.prop(cob, "use_distance_cull")
class CYCLES_OT_use_shading_nodes(Operator):
- """Enable nodes on a material, world or lamp"""
+ """Enable nodes on a material, world or light"""
bl_idname = "cycles.use_shading_nodes"
bl_label = "Use Nodes"
@classmethod
def poll(cls, context):
return (getattr(context, "material", False) or getattr(context, "world", False) or
- getattr(context, "lamp", False))
+ getattr(context, "light", False))
def execute(self, context):
if context.material:
context.material.use_nodes = True
elif context.world:
context.world.use_nodes = True
- elif context.lamp:
- context.lamp.use_nodes = True
+ elif context.light:
+ context.light.use_nodes = True
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):
if not id_data.use_nodes:
layout.operator("cycles.use_shading_nodes", icon='NODETREE')
@@ -964,127 +1305,127 @@ def panel_node_draw(layout, id_data, output_type, input_name):
ntree = id_data.node_tree
- node = find_node(id_data, output_type)
- if not node:
- layout.label(text="No output node")
- else:
+ node = ntree.get_output_node('CYCLES')
+ 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
-class CYCLES_LAMP_PT_preview(CyclesButtonsPanel, Panel):
+class CYCLES_LIGHT_PT_preview(CyclesButtonsPanel, Panel):
bl_label = "Preview"
bl_context = "data"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- return context.lamp and \
- not (context.lamp.type == 'AREA' and
- context.lamp.cycles.is_portal) \
- and CyclesButtonsPanel.poll(context)
+ return (
+ context.light and
+ not (
+ context.light.type == 'AREA' and
+ context.light.cycles.is_portal
+ ) and
+ CyclesButtonsPanel.poll(context)
+ )
def draw(self, context):
- self.layout.template_preview(context.lamp)
+ self.layout.template_preview(context.light)
-class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel):
- bl_label = "Lamp"
+class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
+ bl_label = "Light"
bl_context = "data"
@classmethod
def poll(cls, context):
- return context.lamp and CyclesButtonsPanel.poll(context)
+ return context.light and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
- lamp = context.lamp
- clamp = lamp.cycles
+ light = context.light
+ clamp = light.cycles
# cscene = context.scene.cycles
- layout.prop(lamp, "type", expand=True)
+ layout.prop(light, "type", expand=True)
- split = layout.split()
- col = split.column(align=True)
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- if lamp.type in {'POINT', 'SUN', 'SPOT'}:
- col.prop(lamp, "shadow_soft_size", text="Size")
- elif lamp.type == 'AREA':
- col.prop(lamp, "shape", text="")
+ col = layout.column()
+
+ if light.type in {'POINT', 'SUN', 'SPOT'}:
+ col.prop(light, "shadow_soft_size", text="Size")
+ elif light.type == 'AREA':
+ col.prop(light, "shape", text="Shape")
sub = col.column(align=True)
- if lamp.shape == 'SQUARE':
- sub.prop(lamp, "size")
- elif lamp.shape == 'RECTANGLE':
- sub.prop(lamp, "size", text="Size X")
- sub.prop(lamp, "size_y", text="Size Y")
+ if light.shape in {'SQUARE', 'DISK'}:
+ sub.prop(light, "size")
+ elif light.shape in {'RECTANGLE', 'ELLIPSE'}:
+ sub.prop(light, "size", text="Size X")
+ sub.prop(light, "size_y", text="Y")
- if not (lamp.type == 'AREA' and clamp.is_portal):
- sub = col.column(align=True)
+ if not (light.type == 'AREA' and clamp.is_portal):
+ sub = col.column()
if use_branched_path(context):
subsub = sub.row(align=True)
subsub.active = use_sample_all_lights(context)
subsub.prop(clamp, "samples")
sub.prop(clamp, "max_bounces")
- col = split.column()
-
sub = col.column(align=True)
- sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
+ sub.active = not (light.type == 'AREA' and clamp.is_portal)
sub.prop(clamp, "cast_shadow")
sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
- if lamp.type == 'AREA':
+ if light.type == 'AREA':
col.prop(clamp, "is_portal", text="Portal")
- if lamp.type == 'HEMI':
- layout.label(text="Not supported, interpreted as sun lamp")
-
-class CYCLES_LAMP_PT_nodes(CyclesButtonsPanel, Panel):
+class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
bl_label = "Nodes"
bl_context = "data"
@classmethod
def poll(cls, context):
- return context.lamp and not (context.lamp.type == 'AREA' and
- context.lamp.cycles.is_portal) and \
+ return context.light and not (context.light.type == 'AREA' and
+ context.light.cycles.is_portal) and \
CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
- lamp = context.lamp
- if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
- layout.prop(lamp, "color")
+ light = context.light
+ if not panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface'):
+ layout.prop(light, "color")
-class CYCLES_LAMP_PT_spot(CyclesButtonsPanel, Panel):
+class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
bl_label = "Spot Shape"
bl_context = "data"
@classmethod
def poll(cls, context):
- lamp = context.lamp
- return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
+ light = context.light
+ return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
+ light = context.light
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- lamp = context.lamp
-
- split = layout.split()
-
- col = split.column()
- sub = col.column()
- sub.prop(lamp, "spot_size", text="Size")
- sub.prop(lamp, "spot_blend", text="Blend", slider=True)
-
- col = split.column()
- col.prop(lamp, "show_cone")
+ col = layout.column()
+ col.prop(light, "spot_size", text="Size")
+ col.prop(light, "spot_blend", text="Blend", slider=True)
+ col.prop(light, "show_cone")
class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
@@ -1114,7 +1455,7 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
world = context.world
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
- layout.prop(world, "horizon_color", text="Color")
+ layout.prop(world, "color")
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
@@ -1137,6 +1478,7 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
bl_label = "Ambient Occlusion"
bl_context = "world"
+ bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@@ -1148,15 +1490,17 @@ class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
light = context.world.light_settings
scene = context.scene
- row = layout.row()
- sub = row.row()
+ col = layout.column()
+ sub = col.column()
sub.active = light.use_ambient_occlusion or scene.render.use_simplify
sub.prop(light, "ao_factor", text="Factor")
- row.prop(light, "distance", text="Distance")
+ col.prop(light, "distance", text="Distance")
class CYCLES_WORLD_PT_mist(CyclesButtonsPanel, Panel):
@@ -1168,8 +1512,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
@@ -1221,35 +1565,67 @@ class CYCLES_WORLD_PT_settings(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- world = context.world
- cworld = world.cycles
- # cscene = context.scene.cycles
+ layout.column()
- split = layout.split()
- col = split.column()
+class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
+ bl_label = "Surface"
+ bl_parent_id = "CYCLES_WORLD_PT_settings"
+ bl_context = "world"
+
+ @classmethod
+ def poll(cls, context):
+ return context.world and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- col.label(text="Surface:")
+ world = context.world
+ cworld = world.cycles
+
+ col = layout.column()
col.prop(cworld, "sampling_method", text="Sampling")
- sub = col.column(align=True)
+ sub = col.column()
sub.active = cworld.sampling_method != 'NONE'
subsub = sub.row(align=True)
subsub.active = cworld.sampling_method == 'MANUAL'
subsub.prop(cworld, "sample_map_resolution")
if use_branched_path(context):
- subsub = sub.row(align=True)
+ subsub = sub.column(align=True)
subsub.active = use_sample_all_lights(context)
subsub.prop(cworld, "samples")
sub.prop(cworld, "max_bounces")
- col = split.column()
- col.label(text="Volume:")
+
+class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
+ bl_label = "Volume"
+ bl_parent_id = "CYCLES_WORLD_PT_settings"
+ bl_context = "world"
+
+ @classmethod
+ def poll(cls, context):
+ return context.world and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ world = context.world
+ cworld = world.cycles
+
+ col = layout.column()
+
sub = col.column()
sub.active = use_cpu(context)
- sub.prop(cworld, "volume_sampling", text="")
- col.prop(cworld, "volume_interpolation", text="")
+ sub.prop(cworld, "volume_sampling", text="Sampling")
+ col.prop(cworld, "volume_interpolation", text="Interpolation")
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
@@ -1320,228 +1696,68 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel):
bl_label = "Settings"
bl_context = "material"
-
- @classmethod
- def poll(cls, context):
- return context.material and CyclesButtonsPanel.poll(context)
-
- def draw(self, context):
- layout = self.layout
-
- mat = context.material
- cmat = mat.cycles
-
- split = layout.split()
- col = split.column()
- col.label(text="Surface:")
- col.prop(cmat, "sample_as_light", text="Multiple Importance")
- col.prop(cmat, "use_transparent_shadow")
-
- col.separator()
- col.label(text="Geometry:")
- col.prop(cmat, "displacement_method", text="")
-
- col = split.column()
- col.label(text="Volume:")
- sub = col.column()
- sub.active = use_cpu(context)
- sub.prop(cmat, "volume_sampling", text="")
- col.prop(cmat, "volume_interpolation", text="")
- col.prop(cmat, "homogeneous_volume", text="Homogeneous")
-
- col.separator()
- col.prop(mat, "pass_index")
-
-
-class CYCLES_MATERIAL_PT_viewport(CyclesButtonsPanel, Panel):
- bl_label = "Viewport"
- bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.material and CyclesButtonsPanel.poll(context)
- def draw(self, context):
- mat = context.material
-
+ @staticmethod
+ def draw_shared(self, mat):
layout = self.layout
- split = layout.split()
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- col = split.column(align=True)
- col.label("Color:")
- 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'}
+ layout.prop(mat, "pass_index")
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()
+ self.draw_shared(self, context.material)
- 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)
+class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel):
+ bl_label = "Surface"
+ bl_parent_id = "CYCLES_MATERIAL_PT_settings"
+ bl_context = "material"
- def draw(self, context):
+ @staticmethod
+ def draw_shared(self, mat):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- 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"
+ cmat = mat.cycles
- @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)
+ col = layout.column()
+ col.prop(cmat, "sample_as_light", text="Multiple Importance")
+ col.prop(cmat, "use_transparent_shadow")
+ col.prop(cmat, "displacement_method", text="Displacement Method")
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="")
+ self.draw_shared(self, context.material)
-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)
+class CYCLES_MATERIAL_PT_settings_volume(CyclesButtonsPanel, Panel):
+ bl_label = "Volume"
+ bl_parent_id = "CYCLES_MATERIAL_PT_settings"
+ bl_context = "material"
- def draw(self, context):
+ @staticmethod
+ def draw_shared(self, context, mat):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- 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'}
+ cmat = mat.cycles
- @classmethod
- def poll(cls, context):
- psys = context.particle_system
- return psys and CyclesButtonsPanel.poll(context)
+ col = layout.column()
+ sub = col.column()
+ sub.active = use_cpu(context)
+ sub.prop(cmat, "volume_sampling", text="Sampling")
+ col.prop(cmat, "volume_interpolation", text="Interpolation")
+ col.prop(cmat, "homogeneous_volume", text="Homogeneous")
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")
+ self.draw_shared(self, context, context.material)
class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
@@ -1552,69 +1768,84 @@ class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
scene = context.scene
cscene = scene.cycles
cbk = scene.render.bake
-
- layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
-
- col = layout.column()
- col.prop(cscene, "bake_type")
+ rd = scene.render
col = layout.column()
+ col.prop(rd, "use_bake_multires")
+ if rd.use_bake_multires:
+ col.prop(rd, "bake_type")
- if cscene.bake_type == 'NORMAL':
- col.prop(cbk, "normal_space", text="Space")
-
- 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()
+ col.prop(rd, "bake_margin")
+ col.prop(rd, "use_bake_clear")
- 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 rd.bake_type == 'DISPLACEMENT':
+ col.prop(rd, "use_bake_lores_mesh")
- split = col.split()
- split.active = cbk.use_pass_direct or cbk.use_pass_indirect
+ col.operator("object.bake_image", icon='RENDER_STILL')
- col = split.column()
- col.prop(cbk, "use_pass_diffuse")
- col.prop(cbk, "use_pass_glossy")
- col.prop(cbk, "use_pass_transmission")
+ else:
+ col.prop(cscene, "bake_type")
+
+ col = layout.column()
+
+ if cscene.bake_type == 'NORMAL':
+ col.prop(cbk, "normal_space", text="Space")
+
+ sub = col.column(align=True)
+ sub.prop(cbk, "normal_r", text="Swizzle R")
+ sub.prop(cbk, "normal_g", text="G")
+ sub.prop(cbk, "normal_b", text="B")
+
+ elif cscene.bake_type == 'COMBINED':
+ row = col.row(align=True)
+ row.use_property_split = False
+ row.prop(cbk, "use_pass_direct", toggle=True)
+ row.prop(cbk, "use_pass_indirect", toggle=True)
+
+ col = col.column()
+ col.active = cbk.use_pass_direct or cbk.use_pass_indirect
+ col.prop(cbk, "use_pass_diffuse")
+ col.prop(cbk, "use_pass_glossy")
+ col.prop(cbk, "use_pass_transmission")
+ col.prop(cbk, "use_pass_subsurface")
+ col.prop(cbk, "use_pass_ambient_occlusion")
+ col.prop(cbk, "use_pass_emit")
+
+ elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
+ row = col.row(align=True)
+ row.use_property_split = False
+ 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_subsurface")
- col.prop(cbk, "use_pass_ambient_occlusion")
- col.prop(cbk, "use_pass_emit")
+ layout.separator()
- 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 = layout.column()
+ col.prop(cbk, "margin")
+ col.prop(cbk, "use_clear", text="Clear Image")
- layout.separator()
+ col.separator()
- split = layout.split()
+ 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(cbk, "cage_object", text="Cage Object")
+ else:
+ sub.prop(cbk, "cage_extrusion", text="Ray Distance")
- 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")
+ layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
@@ -1635,7 +1866,7 @@ class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
col = layout.column()
- col.label('CPU Flags:')
+ col.label(text="CPU Flags:")
row = col.row(align=True)
row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
@@ -1648,14 +1879,14 @@ class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
col.separator()
col = layout.column()
- col.label('CUDA Flags:')
+ col.label(text="CUDA Flags:")
col.prop(cscene, "debug_use_cuda_adaptive_compile")
col.prop(cscene, "debug_use_cuda_split_kernel")
col.separator()
col = layout.column()
- col.label('OpenCL Flags:')
+ col.label(text="OpenCL Flags:")
col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
col.prop(cscene, "debug_opencl_device_type", text="Device")
col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
@@ -1668,48 +1899,54 @@ class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
col.prop(cscene, "debug_bvh_type")
-class CYCLES_PARTICLE_PT_curve_settings(CyclesButtonsPanel, Panel):
- bl_label = "Cycles Hair Settings"
- bl_context = "particle"
+class CYCLES_RENDER_PT_simplify(CyclesButtonsPanel, Panel):
+ bl_label = "Simplify"
+ bl_context = "render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'CYCLES'}
- @classmethod
- def poll(cls, context):
- scene = context.scene
- ccscene = scene.cycles_curves
- psys = context.particle_system
- use_curves = ccscene.use_curves and psys
- return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "use_simplify", text="")
def draw(self, context):
- layout = self.layout
+ pass
- psys = context.particle_settings
- cpsys = psys.cycles
- row = layout.row()
- row.prop(cpsys, "shape", text="Shape")
+class CYCLES_RENDER_PT_simplify_viewport(CyclesButtonsPanel, Panel):
+ bl_label = "Viewport"
+ bl_context = "render"
+ bl_parent_id = "CYCLES_RENDER_PT_simplify"
+ COMPAT_ENGINES = {'CYCLES'}
- layout.label(text="Thickness:")
- row = layout.row()
- row.prop(cpsys, "root_width", text="Root")
- row.prop(cpsys, "tip_width", text="Tip")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- row = layout.row()
- row.prop(cpsys, "radius_scale", text="Scaling")
- row.prop(cpsys, "use_closetip", text="Close tip")
+ scene = context.scene
+ rd = scene.render
+ cscene = scene.cycles
+ layout.active = rd.use_simplify
-class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
- bl_label = "Simplify"
- bl_context = "scene"
- COMPAT_ENGINES = {'CYCLES'}
+ col = layout.column()
+ col.prop(rd, "simplify_subdivision", text="Max Subdivision")
+ col.prop(rd, "simplify_child_particles", text="Child Particles")
+ col.prop(cscene, "texture_limit", text="Texture Limit")
+ col.prop(cscene, "ao_bounces", text="AO Bounces")
- def draw_header(self, context):
- rd = context.scene.render
- self.layout.prop(rd, "use_simplify", text="")
+
+class CYCLES_RENDER_PT_simplify_render(CyclesButtonsPanel, Panel):
+ bl_label = "Render"
+ bl_context = "render"
+ bl_parent_id = "CYCLES_RENDER_PT_simplify"
+ COMPAT_ENGINES = {'CYCLES'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
scene = context.scene
rd = scene.render
@@ -1717,80 +1954,116 @@ class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
layout.active = rd.use_simplify
- col = layout.column(align=True)
- col.label(text="Subdivision")
- row = col.row(align=True)
- row.prop(rd, "simplify_subdivision", text="Viewport")
- row.prop(rd, "simplify_subdivision_render", text="Render")
+ col = layout.column()
- col = layout.column(align=True)
- col.label(text="Child Particles")
- row = col.row(align=True)
- row.prop(rd, "simplify_child_particles", text="Viewport")
- row.prop(rd, "simplify_child_particles_render", text="Render")
+ col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
+ col.prop(rd, "simplify_child_particles_render", text="Child Particles")
+ col.prop(cscene, "texture_limit_render", text="Texture Limit")
+ col.prop(cscene, "ao_bounces_render", text="AO Bounces")
- col = layout.column(align=True)
- split = col.split()
- sub = split.column()
- sub.label(text="Texture Limit Viewport")
- sub.prop(cscene, "texture_limit", text="")
- sub = split.column()
- sub.label(text="Texture Limit Render")
- sub.prop(cscene, "texture_limit_render", text="")
- split = layout.split()
- col = split.column()
+class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
+ bl_label = "Culling"
+ bl_context = "render"
+ bl_parent_id = "CYCLES_RENDER_PT_simplify"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'CYCLES'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ rd = scene.render
+ cscene = scene.cycles
+
+ layout.active = rd.use_simplify
+
+ col = layout.column()
col.prop(cscene, "use_camera_cull")
- row = col.row()
- row.active = cscene.use_camera_cull
- row.prop(cscene, "camera_cull_margin")
+ sub = col.column()
+ sub.active = cscene.use_camera_cull
+ sub.prop(cscene, "camera_cull_margin")
- col = split.column()
+ col = layout.column()
col.prop(cscene, "use_distance_cull")
- row = col.row()
- row.active = cscene.use_distance_cull
- row.prop(cscene, "distance_cull_margin", text="Distance")
+ sub = col.column()
+ sub.active = cscene.use_distance_cull
+ sub.prop(cscene, "distance_cull_margin", text="Distance")
- split = layout.split()
- col = split.column()
- col.prop(cscene, "ao_bounces")
- col = split.column()
- col.prop(cscene, "ao_bounces_render")
+class CYCLES_NODE_PT_settings(CyclesNodeButtonsPanel, Panel):
+ bl_label = "Settings"
+ bl_category = "Node"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ snode = context.space_data
+ return CyclesNodeButtonsPanel.poll(context) and \
+ snode.tree_type == 'ShaderNodeTree' and snode.id and \
+ snode.id.bl_rna.identifier == 'Material'
+
+ def draw(self, context):
+ material = context.space_data.id
+ CYCLES_MATERIAL_PT_settings.draw_shared(self, material)
+
+
+class CYCLES_NODE_PT_settings_surface(CyclesNodeButtonsPanel, Panel):
+ bl_label = "Surface"
+ bl_category = "Node"
+ bl_parent_id = "CYCLES_NODE_PT_settings"
+
+ def draw(self, context):
+ material = context.space_data.id
+ CYCLES_MATERIAL_PT_settings_surface.draw_shared(self, material)
+
+
+class CYCLES_NODE_PT_settings_volume(CyclesNodeButtonsPanel, Panel):
+ bl_label = "Volume"
+ bl_category = "Node"
+ bl_parent_id = "CYCLES_NODE_PT_settings"
+
+ def draw(self, context):
+ material = context.space_data.id
+ CYCLES_MATERIAL_PT_settings_volume.draw_shared(self, context, material)
def draw_device(self, context):
scene = context.scene
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- if scene.render.engine == 'CYCLES':
+ if context.engine == 'CYCLES':
from . import engine
cscene = scene.cycles
- layout.prop(cscene, "feature_set")
+ col = layout.column()
+ col.prop(cscene, "feature_set")
- split = layout.split(percentage=1 / 3)
- split.label("Device:")
- row = split.row()
- row.active = show_device_active(context)
- row.prop(cscene, "device", text="")
+ scene = context.scene
+ col = layout.column()
+ col.active = show_device_active(context)
+ col.prop(cscene, "device")
+
+ from . import engine
if engine.with_osl() and use_cpu(context):
- layout.prop(cscene, "shading_system")
+ col.prop(cscene, "shading_system")
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':
+ if view.shading.type == '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)
+ layout.prop(cscene, "preview_pause", icon='PAUSE', text="")
def get_panels():
@@ -1798,49 +2071,15 @@ def get_panels():
'DATA_PT_area',
'DATA_PT_camera_dof',
'DATA_PT_falloff_curve',
- 'DATA_PT_lamp',
+ 'DATA_PT_light',
'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'
+ 'RENDER_PT_simplify',
}
panels = []
@@ -1853,28 +2092,55 @@ def get_panels():
classes = (
- CYCLES_MT_sampling_presets,
- CYCLES_MT_integrator_presets,
+ CYCLES_PT_sampling_presets,
+ CYCLES_PT_integrator_presets,
CYCLES_RENDER_PT_sampling,
- CYCLES_RENDER_PT_geometry,
+ CYCLES_RENDER_PT_sampling_sub_samples,
+ CYCLES_RENDER_PT_sampling_advanced,
CYCLES_RENDER_PT_light_paths,
+ CYCLES_RENDER_PT_light_paths_max_bounces,
+ CYCLES_RENDER_PT_light_paths_clamping,
+ CYCLES_RENDER_PT_light_paths_caustics,
+ CYCLES_RENDER_PT_volumes,
+ CYCLES_RENDER_PT_subdivision,
+ CYCLES_RENDER_PT_hair,
+ CYCLES_RENDER_PT_simplify,
+ CYCLES_RENDER_PT_simplify_viewport,
+ CYCLES_RENDER_PT_simplify_render,
+ CYCLES_RENDER_PT_simplify_culling,
CYCLES_RENDER_PT_motion_blur,
+ CYCLES_RENDER_PT_motion_blur_curve,
CYCLES_RENDER_PT_film,
+ CYCLES_RENDER_PT_film_pixel_filter,
+ CYCLES_RENDER_PT_film_transparency,
CYCLES_RENDER_PT_performance,
- CYCLES_RENDER_PT_layer_options,
- CYCLES_RENDER_PT_layer_passes,
- CYCLES_RENDER_PT_views,
+ CYCLES_RENDER_PT_performance_threads,
+ CYCLES_RENDER_PT_performance_tiles,
+ CYCLES_RENDER_PT_performance_acceleration_structure,
+ CYCLES_RENDER_PT_performance_final_render,
+ CYCLES_RENDER_PT_performance_viewport,
+ CYCLES_RENDER_PT_filter,
+ CYCLES_RENDER_PT_override,
+ CYCLES_RENDER_PT_passes,
+ CYCLES_RENDER_PT_passes_data,
+ CYCLES_RENDER_PT_passes_light,
+ CYCLES_RENDER_PT_passes_crypto,
+ CYCLES_RENDER_PT_passes_debug,
CYCLES_RENDER_PT_denoising,
CYCLES_PT_post_processing,
CYCLES_CAMERA_PT_dof,
+ CYCLES_CAMERA_PT_dof_aperture,
+ CYCLES_CAMERA_PT_dof_viewport,
CYCLES_PT_context_material,
CYCLES_OBJECT_PT_motion_blur,
CYCLES_OBJECT_PT_cycles_settings,
+ CYCLES_OBJECT_PT_cycles_settings_ray_visibility,
+ CYCLES_OBJECT_PT_cycles_settings_performance,
CYCLES_OT_use_shading_nodes,
- CYCLES_LAMP_PT_preview,
- CYCLES_LAMP_PT_lamp,
- CYCLES_LAMP_PT_nodes,
- CYCLES_LAMP_PT_spot,
+ CYCLES_LIGHT_PT_preview,
+ CYCLES_LIGHT_PT_light,
+ CYCLES_LIGHT_PT_nodes,
+ CYCLES_LIGHT_PT_spot,
CYCLES_WORLD_PT_preview,
CYCLES_WORLD_PT_surface,
CYCLES_WORLD_PT_volume,
@@ -1882,28 +2148,27 @@ classes = (
CYCLES_WORLD_PT_mist,
CYCLES_WORLD_PT_ray_visibility,
CYCLES_WORLD_PT_settings,
+ CYCLES_WORLD_PT_settings_surface,
+ CYCLES_WORLD_PT_settings_volume,
CYCLES_MATERIAL_PT_preview,
CYCLES_MATERIAL_PT_surface,
CYCLES_MATERIAL_PT_volume,
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_MATERIAL_PT_settings_surface,
+ CYCLES_MATERIAL_PT_settings_volume,
CYCLES_RENDER_PT_bake,
CYCLES_RENDER_PT_debug,
- CYCLES_PARTICLE_PT_curve_settings,
- CYCLES_SCENE_PT_simplify,
+ CYCLES_NODE_PT_settings,
+ CYCLES_NODE_PT_settings_surface,
+ CYCLES_NODE_PT_settings_volume,
)
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():
@@ -1916,7 +2181,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 3a4b13ef9d2..178f1162568 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -22,45 +22,6 @@ import math
from bpy.app.handlers import persistent
-def check_is_new_shading_ntree(node_tree):
- for node in node_tree.nodes:
- # If material has any node with ONLY new shading system
- # compatibility then it's considered a Cycles material
- # and versioning code would need to perform on it.
- #
- # We can not check for whether NEW_SHADING in compatibility
- # because some nodes could have compatibility with both old
- # and new shading system and they can't be used for any
- # decision here.
- if node.shading_compatibility == {'NEW_SHADING'}:
- return True
-
- # If node is only compatible with old shading system
- # then material can not be Cycles material and we
- # can stopiterating nodes now.
- if node.shading_compatibility == {'OLD_SHADING'}:
- return False
- return False
-
-
-def check_is_new_shading_material(material):
- if not material.node_tree:
- return False
- return check_is_new_shading_ntree(material.node_tree)
-
-
-def check_is_new_shading_world(world):
- if not world.node_tree:
- return False
- return check_is_new_shading_ntree(world.node_tree)
-
-
-def check_is_new_shading_lamp(lamp):
- if not lamp.node_tree:
- return False
- return check_is_new_shading_ntree(lamp.node_tree)
-
-
def foreach_notree_node(nodetree, callback, traversed):
if nodetree in traversed:
return
@@ -74,23 +35,23 @@ def foreach_notree_node(nodetree, callback, traversed):
def foreach_cycles_node(callback):
traversed = set()
for material in bpy.data.materials:
- if check_is_new_shading_material(material):
+ if material.node_tree:
foreach_notree_node(
material.node_tree,
callback,
traversed,
)
for world in bpy.data.worlds:
- if check_is_new_shading_world(world):
+ if world.node_tree:
foreach_notree_node(
world.node_tree,
callback,
traversed,
)
- for lamp in bpy.data.lamps:
- if check_is_new_shading_world(lamp):
+ for light in bpy.data.lights:
+ if light.node_tree:
foreach_notree_node(
- lamp.node_tree,
+ light.node_tree,
callback,
traversed,
)
@@ -109,10 +70,10 @@ def displacement_node_insert(material, nodetree, traversed):
displacement_links = []
for link in nodetree.links:
if (
- link.to_node.bl_idname == 'ShaderNodeOutputMaterial' and
- link.from_node.bl_idname != 'ShaderNodeDisplacement' and
- link.to_socket.identifier == 'Displacement'
- ):
+ link.to_node.bl_idname == 'ShaderNodeOutputMaterial' and
+ link.from_node.bl_idname != 'ShaderNodeDisplacement' and
+ link.to_socket.identifier == 'Displacement'
+ ):
displacement_links.append(link)
# Replace links with displacement node
@@ -137,7 +98,7 @@ def displacement_node_insert(material, nodetree, traversed):
def displacement_nodes_insert():
traversed = set()
for material in bpy.data.materials:
- if check_is_new_shading_material(material):
+ if material.node_tree:
displacement_node_insert(material, material.node_tree, traversed)
@@ -198,7 +159,7 @@ def square_roughness_node_insert(material, nodetree, traversed):
def square_roughness_nodes_insert():
traversed = set()
for material in bpy.data.materials:
- if check_is_new_shading_material(material):
+ if material.node_tree:
square_roughness_node_insert(material, material.node_tree, traversed)
@@ -314,15 +275,15 @@ def ambient_occlusion_node_relink(material, nodetree, traversed):
def ambient_occlusion_nodes_relink():
traversed = set()
for material in bpy.data.materials:
- if check_is_new_shading_material(material):
+ if material.node_tree:
ambient_occlusion_node_relink(material, material.node_tree, traversed)
@persistent
def do_versions(self):
- if bpy.context.user_preferences.version <= (2, 78, 1):
- prop = bpy.context.user_preferences.addons[__package__].preferences
- system = bpy.context.user_preferences.system
+ if bpy.context.preferences.version <= (2, 78, 1):
+ prop = bpy.context.preferences.addons[__package__].preferences
+ system = bpy.context.preferences.system
if not prop.is_property_set("compute_device_type"):
# Device might not currently be available so this can fail
try:
@@ -348,11 +309,9 @@ def do_versions(self):
for scene in bpy.data.scenes:
cscene = scene.cycles
sample_clamp = cscene.get("sample_clamp", False)
- if (
- sample_clamp and
+ if (sample_clamp and
not cscene.is_property_set("sample_clamp_direct") and
- not cscene.is_property_set("sample_clamp_indirect")
- ):
+ not cscene.is_property_set("sample_clamp_indirect")):
cscene.sample_clamp_direct = sample_clamp
cscene.sample_clamp_indirect = sample_clamp
@@ -368,11 +327,10 @@ def do_versions(self):
if bpy.data.version <= (2, 72, 0):
for scene in bpy.data.scenes:
cscene = scene.cycles
- if (
- cscene.get("no_caustics", False) and
+ if (cscene.get("no_caustics", False) and
not cscene.is_property_set("caustics_reflective") and
- not cscene.is_property_set("caustics_refractive")
- ):
+ not cscene.is_property_set("caustics_refractive")):
+
cscene.caustics_reflective = False
cscene.caustics_refractive = False
@@ -409,12 +367,12 @@ def do_versions(self):
if not cscene.is_property_set("tile_order"):
cscene.tile_order = 'CENTER'
- for lamp in bpy.data.lamps:
- clamp = lamp.cycles
+ for light in bpy.data.lights:
+ clight = light.cycles
# MIS
- if not clamp.is_property_set("use_multiple_importance_sampling"):
- clamp.use_multiple_importance_sampling = False
+ if not clight.is_property_set("use_multiple_importance_sampling"):
+ clight.use_multiple_importance_sampling = False
for mat in bpy.data.materials:
cmat = mat.cycles
@@ -463,7 +421,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):
@@ -474,11 +433,24 @@ 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()
- if bpy.data.version <= (2, 79, 4):
+ if bpy.data.version <= (2, 80, 15):
+ # Copy cycles hair settings to internal settings
+ for part in bpy.data.particles:
+ cpart = part.get("cycles", None)
+ if cpart:
+ part.shape = cpart.get("shape", 0.0)
+ part.root_radius = cpart.get("root_width", 1.0)
+ part.tip_radius = cpart.get("tip_width", 0.0)
+ part.radius_scale = cpart.get("radius_scale", 0.01)
+ part.use_close_tip = cpart.get("use_closetip", True)
+
+ if bpy.data.version <= (2, 79, 4) or \
+ (bpy.data.version >= (2, 80, 0) and bpy.data.version <= (2, 80, 18)):
for world in bpy.data.worlds:
cworld = world.cycles
# World MIS
@@ -490,7 +462,8 @@ def do_versions(self):
ambient_occlusion_nodes_relink()
- if bpy.data.version <= (2, 79, 6):
+ if bpy.data.version <= (2, 79, 6) or \
+ (bpy.data.version >= (2, 80, 0) and bpy.data.version <= (2, 80, 41)):
# Change default to bump again.
for mat in bpy.data.materials:
cmat = mat.cycles
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 5a447a347a3..21efba4cdf0 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;
@@ -228,12 +228,17 @@ static void blender_camera_from_object(BlenderCamera *bcam,
bcam->sensor_fit = BlenderCamera::HORIZONTAL;
else
bcam->sensor_fit = BlenderCamera::VERTICAL;
-
- bcam->motion_steps = object_motion_steps(b_ob, b_ob);
}
- else {
- /* from lamp not implemented yet */
+ else if(b_ob_data.is_a(&RNA_Light)) {
+ /* Can also look through spot light. */
+ BL::SpotLight b_light(b_ob_data);
+ float lens = 16.0f / tanf(b_light.spot_size() * 0.5f);
+ if (lens > 0.0f) {
+ bcam->lens = lens;
+ }
}
+
+ bcam->motion_steps = object_motion_steps(b_ob, b_ob);
}
static Transform blender_camera_matrix(const Transform& tfm,
@@ -643,7 +648,7 @@ static void blender_camera_from_view(BlenderCamera *bcam,
if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
/* camera view */
- BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
+ BL::Object b_ob = (b_v3d.use_local_camera())? b_v3d.camera(): b_scene.camera();
if(b_ob) {
blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama);
@@ -779,7 +784,7 @@ static void blender_camera_border(BlenderCamera *bcam,
return;
}
- BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
+ BL::Object b_ob = (b_v3d.use_local_camera())? b_v3d.camera(): b_scene.camera();
if(!b_ob)
return;
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index b5e49bbeeef..48dc90417ca 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -136,9 +136,9 @@ static bool ObtainCacheParticleData(Mesh *mesh,
if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
int shader = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
- int draw_step = background ? b_part.render_step() : b_part.draw_step();
+ int display_step = background ? b_part.render_step() : b_part.display_step();
int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
int totcurves = totchild;
if(b_part.child_type() == 0 || totchild == 0)
@@ -147,22 +147,20 @@ static bool ObtainCacheParticleData(Mesh *mesh,
if(totcurves == 0)
continue;
- int ren_step = (1 << draw_step) + 1;
+ int ren_step = (1 << display_step) + 1;
if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
ren_step += b_part.kink_extra_steps();
- PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
-
CData->psys_firstcurve.push_back_slow(curvenum);
CData->psys_curvenum.push_back_slow(totcurves);
CData->psys_shader.push_back_slow(shader);
- float radius = get_float(cpsys, "radius_scale") * 0.5f;
+ float radius = b_part.radius_scale() * 0.5f;
- CData->psys_rootradius.push_back_slow(radius * get_float(cpsys, "root_width"));
- CData->psys_tipradius.push_back_slow(radius * get_float(cpsys, "tip_width"));
- CData->psys_shape.push_back_slow(get_float(cpsys, "shape"));
- CData->psys_closetip.push_back_slow(get_boolean(cpsys, "use_closetip"));
+ CData->psys_rootradius.push_back_slow(radius * b_part.root_radius());
+ CData->psys_tipradius.push_back_slow(radius * b_part.tip_radius());
+ CData->psys_shape.push_back_slow(b_part.shape());
+ CData->psys_closetip.push_back_slow(b_part.use_close_tip());
int pa_no = 0;
if(!(b_part.child_type() == 0) && totchild != 0)
@@ -231,7 +229,7 @@ static bool ObtainCacheParticleUV(Mesh *mesh,
if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
int totcurves = totchild;
if(b_part.child_type() == 0 || totchild == 0)
@@ -251,11 +249,11 @@ static bool ObtainCacheParticleUV(Mesh *mesh,
b_psys.particles.begin(b_pa);
for(; pa_no < totparts+totchild; pa_no++) {
/* Add UVs */
- BL::Mesh::tessface_uv_textures_iterator l;
- b_mesh->tessface_uv_textures.begin(l);
+ BL::Mesh::uv_layers_iterator l;
+ b_mesh->uv_layers.begin(l);
float3 uv = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->tessface_uv_textures.length())
+ if(b_mesh->uv_layers.length())
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
CData->curve_uv.push_back_slow(uv);
@@ -290,7 +288,7 @@ static bool ObtainCacheParticleVcol(Mesh *mesh,
if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
int totcurves = totchild;
if(b_part.child_type() == 0 || totchild == 0)
@@ -310,11 +308,11 @@ static bool ObtainCacheParticleVcol(Mesh *mesh,
b_psys.particles.begin(b_pa);
for(; pa_no < totparts+totchild; pa_no++) {
/* Add vertex colors */
- BL::Mesh::tessface_vertex_colors_iterator l;
- b_mesh->tessface_vertex_colors.begin(l);
+ BL::Mesh::vertex_colors_iterator l;
+ b_mesh->vertex_colors.begin(l);
float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->tessface_vertex_colors.length())
+ if(b_mesh->vertex_colors.length())
b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
CData->curve_vcol.push_back_slow(vcol);
@@ -328,18 +326,6 @@ static bool ObtainCacheParticleVcol(Mesh *mesh,
return true;
}
-static void set_resolution(BL::BlendData *b_data, 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(*b_data, *scene, *b_ob, (render)? 2: 1);
- }
- }
-}
-
static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
float3 RotCam, bool is_ortho)
{
@@ -974,9 +960,6 @@ void BlenderSync::sync_curves(Mesh *mesh,
ParticleCurveData CData;
- if(!preview)
- set_resolution(&b_data, &b_ob, &b_scene, true);
-
ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
/* add hair geometry to mesh */
@@ -1039,10 +1022,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
/* create vertex color attributes */
if(!motion) {
- BL::Mesh::tessface_vertex_colors_iterator l;
+ BL::Mesh::vertex_colors_iterator l;
int vcol_num = 0;
- for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
+ for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
continue;
@@ -1076,10 +1059,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
/* create UV attributes */
if(!motion) {
- BL::Mesh::tessface_uv_textures_iterator l;
+ BL::Mesh::uv_layers_iterator l;
int uv_num = 0;
- for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) {
+ for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
bool active_render = l->active_render();
AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
ustring name = ustring(l->name().c_str());
@@ -1120,9 +1103,6 @@ void BlenderSync::sync_curves(Mesh *mesh,
}
}
- if(!preview)
- set_resolution(&b_data, &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 8d2ade1e30b..8e81e3ac121 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -35,46 +35,6 @@
CCL_NAMESPACE_BEGIN
-/* Per-face bit flags. */
-enum {
- /* Face has no special flags. */
- FACE_FLAG_NONE = (0 << 0),
- /* Quad face was split using 1-3 diagonal. */
- FACE_FLAG_DIVIDE_13 = (1 << 0),
- /* Quad face was split using 2-4 diagonal. */
- FACE_FLAG_DIVIDE_24 = (1 << 1),
-};
-
-/* Get vertex indices to create triangles from a given face.
- *
- * Two triangles has vertex indices in the original Blender-side face.
- * If face is already a quad tri_b will not be initialized.
- */
-inline void face_split_tri_indices(const int face_flag,
- int tri_a[3],
- int tri_b[3])
-{
- if(face_flag & FACE_FLAG_DIVIDE_24) {
- tri_a[0] = 0;
- tri_a[1] = 1;
- tri_a[2] = 3;
-
- tri_b[0] = 2;
- tri_b[1] = 3;
- tri_b[2] = 1;
- }
- else {
- /* Quad with FACE_FLAG_DIVIDE_13 or single triangle. */
- tri_a[0] = 0;
- tri_a[1] = 1;
- tri_a[2] = 2;
-
- tri_b[0] = 0;
- tri_b[1] = 2;
- tri_b[2] = 3;
- }
-}
-
/* Tangent Space */
struct MikkUserData {
@@ -379,8 +339,6 @@ static void create_mesh_volume_attributes(Scene *scene,
static void attr_create_vertex_color(Scene *scene,
Mesh *mesh,
BL::Mesh& b_mesh,
- const vector<int>& nverts,
- const vector<int>& face_flags,
bool subdivision)
{
if(subdivision) {
@@ -401,15 +359,15 @@ static void attr_create_vertex_color(Scene *scene,
int n = p->loop_total();
for(int i = 0; i < n; i++) {
float3 color = get_float3(l->data[p->loop_start() + i].color());
- /* Encode vertex color using the sRGB curve. */
+ /* Compress/encode vertex color using the sRGB curve. */
*(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
}
}
}
}
else {
- BL::Mesh::tessface_vertex_colors_iterator l;
- for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
+ BL::Mesh::vertex_colors_iterator l;
+ for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
continue;
@@ -417,35 +375,20 @@ static void attr_create_vertex_color(Scene *scene,
TypeDesc::TypeColor,
ATTR_ELEMENT_CORNER_BYTE);
- BL::MeshColorLayer::data_iterator c;
+ BL::Mesh::loop_triangles_iterator t;
uchar4 *cdata = attr->data_uchar4();
- size_t i = 0;
-
- for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
- int tri_a[3], tri_b[3];
- face_split_tri_indices(face_flags[i], tri_a, tri_b);
-
- /* Encode vertex color using the sRGB curve. */
- uchar4 colors[4];
- colors[0] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color1())));
- colors[1] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color2())));
- colors[2] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color3())));
- if(nverts[i] == 4) {
- colors[3] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color4())));
- }
- cdata[0] = colors[tri_a[0]];
- cdata[1] = colors[tri_a[1]];
- cdata[2] = colors[tri_a[2]];
-
- if(nverts[i] == 4) {
- cdata[3] = colors[tri_b[0]];
- cdata[4] = colors[tri_b[1]];
- cdata[5] = colors[tri_b[2]];
- cdata += 6;
- }
- else
- cdata += 3;
+ for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+ int3 li = get_int3(t->loops());
+ float3 c1 = get_float3(l->data[li[0]].color());
+ float3 c2 = get_float3(l->data[li[1]].color());
+ float3 c3 = get_float3(l->data[li[2]].color());
+
+ /* Compress/encode vertex color using the sRGB curve. */
+ cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1));
+ cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2));
+ cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3));
+ cdata += 3;
}
}
}
@@ -454,14 +397,12 @@ static void attr_create_vertex_color(Scene *scene,
/* Create uv map attributes. */
static void attr_create_uv_map(Scene *scene,
Mesh *mesh,
- BL::Mesh& b_mesh,
- const vector<int>& nverts,
- const vector<int>& face_flags)
+ BL::Mesh& b_mesh)
{
- if(b_mesh.tessface_uv_textures.length() != 0) {
- BL::Mesh::tessface_uv_textures_iterator l;
+ if(b_mesh.uv_layers.length() != 0) {
+ BL::Mesh::uv_layers_iterator l;
- for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
+ for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) {
const 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());
@@ -493,33 +434,15 @@ static void attr_create_uv_map(Scene *scene,
ATTR_ELEMENT_CORNER);
}
- BL::MeshTextureFaceLayer::data_iterator t;
+ BL::Mesh::loop_triangles_iterator t;
float3 *fdata = uv_attr->data_float3();
- size_t i = 0;
-
- for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
- int tri_a[3], tri_b[3];
- face_split_tri_indices(face_flags[i], tri_a, tri_b);
-
- float3 uvs[4];
- uvs[0] = get_float3(t->uv1());
- uvs[1] = get_float3(t->uv2());
- uvs[2] = get_float3(t->uv3());
- if(nverts[i] == 4) {
- uvs[3] = get_float3(t->uv4());
- }
- fdata[0] = uvs[tri_a[0]];
- fdata[1] = uvs[tri_a[1]];
- fdata[2] = uvs[tri_a[2]];
+ for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+ int3 li = get_int3(t->loops());
+ fdata[0] = get_float3(l->data[li[0]].uv());
+ fdata[1] = get_float3(l->data[li[1]].uv());
+ fdata[2] = get_float3(l->data[li[2]].uv());
fdata += 3;
-
- if(nverts[i] == 4) {
- fdata[0] = uvs[tri_b[0]];
- fdata[1] = uvs[tri_b[1]];
- fdata[2] = uvs[tri_b[2]];
- fdata += 3;
- }
}
}
@@ -563,7 +486,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
@@ -822,7 +745,7 @@ static void create_mesh(Scene *scene,
{
/* count vertices and faces */
int numverts = b_mesh.vertices.length();
- int numfaces = (!subdivision) ? b_mesh.tessfaces.length() : b_mesh.polygons.length();
+ int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
int numtris = 0;
int numcorners = 0;
int numngons = 0;
@@ -833,17 +756,11 @@ static void create_mesh(Scene *scene,
return;
}
- BL::Mesh::vertices_iterator v;
- BL::Mesh::tessfaces_iterator f;
- BL::Mesh::polygons_iterator p;
-
if(!subdivision) {
- for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
- int4 vi = get_int4(f->vertices_raw());
- numtris += (vi[3] == 0)? 1: 2;
- }
+ numtris = numfaces;
}
else {
+ BL::Mesh::polygons_iterator p;
for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
numngons += (p->loop_total() == 4)? 0: 1;
numcorners += p->loop_total();
@@ -855,6 +772,7 @@ static void create_mesh(Scene *scene,
mesh->reserve_subd_faces(numfaces, numngons, numcorners);
/* create vertex coordinates and normals */
+ BL::Mesh::vertices_iterator v;
for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
mesh->add_vertex(get_float3(v->co()));
@@ -869,7 +787,7 @@ static void create_mesh(Scene *scene,
/* create generated coordinates from undeformed coordinates */
const bool need_default_tangent =
(subdivision == false) &&
- (b_mesh.tessface_uv_textures.length() == 0) &&
+ (b_mesh.uv_layers.length() == 0) &&
(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
if(mesh->need_attribute(scene, ATTR_STD_GENERATED) ||
need_default_tangent)
@@ -889,20 +807,19 @@ static void create_mesh(Scene *scene,
}
/* create faces */
- vector<int> nverts(numfaces);
- vector<int> face_flags(numfaces, FACE_FLAG_NONE);
- int fi = 0;
-
if(!subdivision) {
- for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
- int4 vi = get_int4(f->vertices_raw());
- int n = (vi[3] == 0)? 3: 4;
- int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
- bool smooth = f->use_smooth() || use_loop_normals;
+ BL::Mesh::loop_triangles_iterator t;
+
+ for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+ BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
+ int3 vi = get_int3(t->vertices());
+
+ int shader = clamp(p.material_index(), 0, used_shaders.size()-1);
+ bool smooth = p.use_smooth() || use_loop_normals;
if(use_loop_normals) {
- BL::Array<float, 12> loop_normals = f->split_normals();
- for(int i = 0; i < n; i++) {
+ BL::Array<float, 9> loop_normals = t->split_normals();
+ for(int i = 0; i < 3; i++) {
N[vi[i]] = make_float3(loop_normals[i * 3],
loop_normals[i * 3 + 1],
loop_normals[i * 3 + 2]);
@@ -913,28 +830,11 @@ static void create_mesh(Scene *scene,
*
* NOTE: Autosmooth is already taken care about.
*/
- if(n == 4) {
- if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
- is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
- {
- mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
- mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
- face_flags[fi] |= FACE_FLAG_DIVIDE_24;
- }
- else {
- mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
- mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
- face_flags[fi] |= FACE_FLAG_DIVIDE_13;
- }
- }
- else {
- mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
- }
-
- nverts[fi] = n;
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
}
}
else {
+ BL::Mesh::polygons_iterator p;
vector<int> vi;
for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
@@ -957,13 +857,13 @@ static void create_mesh(Scene *scene,
* The calculate functions will check whether they're needed or not.
*/
attr_create_pointiness(scene, mesh, b_mesh, subdivision);
- attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
+ attr_create_vertex_color(scene, mesh, b_mesh, subdivision);
if(subdivision) {
attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
}
else {
- attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);
+ attr_create_uv_map(scene, mesh, b_mesh);
}
/* for volume objects, create a matrix to transform from object space to
@@ -989,7 +889,7 @@ static void create_subd_mesh(Scene *scene,
int max_subdivisions)
{
BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length()-1]);
- bool subdivide_uvs = subsurf_mod.use_subsurf_uv();
+ bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs);
@@ -1071,22 +971,17 @@ 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)
+ bool show_self,
+ bool show_particles)
{
- /* When viewport display is not needed during render we can force some
- * caches to be releases from blender side in order to reduce peak memory
- * footprint during synchronization process.
- */
- const bool is_interface_locked = b_engine.render() &&
- b_engine.render().use_lock_interface();
- const bool can_free_caches = BlenderSession::headless || is_interface_locked;
-
/* 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;
@@ -1111,10 +1006,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;
@@ -1166,36 +1061,27 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
mesh->name = ustring(b_ob_data.name().c_str());
if(requested_geometry_flags != Mesh::GEOMETRY_NONE) {
- /* mesh objects does have special handle in the dependency graph,
- * they're ensured to have properly updated.
- *
- * updating meshes here will end up having derived mesh referencing
- * freed data from the blender side.
- */
- if(preview && b_ob.type() != BL::Object::type_MESH)
- b_ob.update_from_editmode(b_data);
-
- bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
-
- mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
-
- /* Disable adaptive subdivision while baking as the baking system
- * currently doesnt support the topology and will crash.
- */
+ /* Adaptive subdivision setup. Not for baking since that requires
+ * exact mapping to the Blender mesh. */
if(scene->bake_manager->get_baking()) {
mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
}
+ else {
+ mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
+ }
+
+ /* For some reason, meshes do not need this... */
+ bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(b_data,
b_ob,
- b_scene,
- true,
- !preview,
+ b_depsgraph,
need_undeformed,
mesh->subdivision_type);
if(b_mesh) {
- if(render_layer.use_surfaces && !hide_tris) {
+ /* Sync mesh itself. */
+ if(view_layer.use_surfaces && show_self) {
if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders,
dicing_rate, max_subdivisions);
@@ -1205,15 +1091,12 @@ 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)
+ /* Sync hair curves. */
+ if(view_layer.use_hair && show_particles && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
sync_curves(mesh, b_mesh, b_ob, false);
-
- if(can_free_caches) {
- b_ob.cache_release();
}
- /* free derived mesh */
- b_data.meshes.remove(b_mesh, false, true, false);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
}
}
mesh->geometry_flags = requested_geometry_flags;
@@ -1233,7 +1116,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)
{
@@ -1276,9 +1160,7 @@ 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,
Mesh::SUBDIVISION_NONE);
}
@@ -1390,7 +1272,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
sync_curves(mesh, b_mesh, b_ob, true, motion_step);
/* free derived mesh */
- b_data.meshes.remove(b_mesh, false, true, false);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index a05c982b367..37fea2417ba 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -89,7 +89,7 @@ bool BlenderSync::object_is_light(BL::Object& b_ob)
{
BL::ID b_ob_data = b_ob.data();
- return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
+ return (b_ob_data && b_ob_data.is_a(&RNA_Light));
}
static uint object_ray_visibility(BL::Object& b_ob)
@@ -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)
@@ -126,45 +127,60 @@ void BlenderSync::sync_light(BL::Object& b_parent,
return;
}
- BL::Lamp b_lamp(b_ob.data());
+ BL::Light b_light(b_ob.data());
/* type */
- switch(b_lamp.type()) {
- case BL::Lamp::type_POINT: {
- BL::PointLamp b_point_lamp(b_lamp);
- light->size = b_point_lamp.shadow_soft_size();
+ switch(b_light.type()) {
+ case BL::Light::type_POINT: {
+ BL::PointLight b_point_light(b_light);
+ light->size = b_point_light.shadow_soft_size();
light->type = LIGHT_POINT;
break;
}
- case BL::Lamp::type_SPOT: {
- BL::SpotLamp b_spot_lamp(b_lamp);
- light->size = b_spot_lamp.shadow_soft_size();
+ case BL::Light::type_SPOT: {
+ BL::SpotLight b_spot_light(b_light);
+ light->size = b_spot_light.shadow_soft_size();
light->type = LIGHT_SPOT;
- light->spot_angle = b_spot_lamp.spot_size();
- light->spot_smooth = b_spot_lamp.spot_blend();
+ light->spot_angle = b_spot_light.spot_size();
+ light->spot_smooth = b_spot_light.spot_blend();
break;
}
- case BL::Lamp::type_HEMI: {
+ /* Hemi were removed from 2.8 */
+ // case BL::Light::type_HEMI: {
+ // light->type = LIGHT_DISTANT;
+ // light->size = 0.0f;
+ // break;
+ // }
+ case BL::Light::type_SUN: {
+ BL::SunLight b_sun_light(b_light);
+ light->size = b_sun_light.shadow_soft_size();
light->type = LIGHT_DISTANT;
- light->size = 0.0f;
break;
}
- case BL::Lamp::type_SUN: {
- BL::SunLamp b_sun_lamp(b_lamp);
- light->size = b_sun_lamp.shadow_soft_size();
- light->type = LIGHT_DISTANT;
- break;
- }
- case BL::Lamp::type_AREA: {
- BL::AreaLamp b_area_lamp(b_lamp);
+ case BL::Light::type_AREA: {
+ BL::AreaLight b_area_light(b_light);
light->size = 1.0f;
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;
+ light->sizeu = b_area_light.size();
+ switch(b_area_light.shape()) {
+ case BL::AreaLight::shape_SQUARE:
+ light->sizev = light->sizeu;
+ light->round = false;
+ break;
+ case BL::AreaLight::shape_RECTANGLE:
+ light->sizev = b_area_light.size_y();
+ light->round = false;
+ break;
+ case BL::AreaLight::shape_DISK:
+ light->sizev = light->sizeu;
+ light->round = true;
+ break;
+ case BL::AreaLight::shape_ELLIPSE:
+ light->sizev = b_area_light.size_y();
+ light->round = true;
+ break;
+ }
light->type = LIGHT_AREA;
break;
}
@@ -177,32 +193,32 @@ void BlenderSync::sync_light(BL::Object& b_parent,
/* shader */
vector<Shader*> used_shaders;
- find_shader(b_lamp, used_shaders, scene->default_light);
+ find_shader(b_light, used_shaders, scene->default_light);
light->shader = used_shaders[0];
/* shadow */
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
- light->cast_shadow = get_boolean(clamp, "cast_shadow");
- light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling");
+ PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
+ light->cast_shadow = get_boolean(clight, "cast_shadow");
+ light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
- int samples = get_int(clamp, "samples");
+ int samples = get_int(clight, "samples");
if(get_boolean(cscene, "use_square_samples"))
light->samples = samples * samples;
else
light->samples = samples;
- light->max_bounces = get_int(clamp, "max_bounces");
+ light->max_bounces = get_int(clight, "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);
}
if(light->type == LIGHT_AREA)
- light->is_portal = get_boolean(clamp, "is_portal");
+ light->is_portal = get_boolean(clight, "is_portal");
else
light->is_portal = false;
@@ -275,24 +291,47 @@ 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,
- uint layer_flag,
+Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
+ BL::ViewLayer& b_view_layer,
+ BL::DepsgraphObjectInstance& b_instance,
float motion_time,
- bool hide_tris,
+ bool show_self,
+ bool show_particles,
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_instance.is_instance();
+ BL::Object b_ob = b_instance.object();
+ BL::Object b_parent = is_instance ? b_instance.parent()
+ : b_instance.object();
+ BL::Object b_ob_instance = is_instance ? b_instance.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_instance.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 && object_is_light(b_ob)) {
+ /* TODO: don't use lights for excluded layers used as mask layer,
+ * when dynamic overrides are back. */
+#if 0
+ if(!((layer_flag & view_layer.holdout_layer) &&
+ (layer_flag & view_layer.exclude_layer)))
+#endif
+ {
+ sync_light(b_parent,
+ persistent_id,
+ b_ob,
+ b_ob_instance,
+ is_instance ? b_instance.random_id() : 0,
+ tfm,
+ use_portal);
+ }
return NULL;
}
@@ -309,21 +348,24 @@ 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 ||
- get_boolean(cobject, "is_holdout");
+ bool use_holdout = get_boolean(cobject, "is_holdout") ||
+ b_parent.holdout_get(b_view_layer);
uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
if(b_parent.ptr.data != b_ob.ptr.data) {
visibility &= object_ray_visibility(b_parent);
}
- /* Make holdout objects on excluded layer invisible for non-camera rays. */
- if(use_holdout && (layer_flag & render_layer.exclude_layer)) {
+ /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */
+#if 0
+ if(use_holdout && (layer_flag & view_layer.exclude_layer)) {
visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
}
+#endif
- /* Hide objects not on render layer from camera rays. */
- if(!(layer_flag & render_layer.layer)) {
+ /* Clear camera visibility for indirect only objects. */
+ bool use_indirect_only = b_parent.indirect_only_get(b_view_layer);
+ if(use_indirect_only) {
visibility &= ~PATH_RAY_CAMERA;
}
@@ -333,7 +375,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 */
@@ -349,7 +391,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;
@@ -362,7 +404,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, show_self, show_particles);
/* special case not tracked by object update flags */
@@ -444,10 +486,10 @@ 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_instance.orco()) - make_float3(0.5f, 0.5f, 0.5f);
+ object->dupli_uv = get_float2(b_instance.uv());
+ object->random_id = b_instance.random_id();
}
else {
object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
@@ -458,94 +500,19 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
object->tag_update(scene);
}
- return object;
-}
-
-static bool object_render_hide_original(BL::Object::type_enum ob_type,
- BL::Object::dupli_type_enum dupli_type)
-{
- /* metaball exception, they duplicate self */
- if(ob_type == BL::Object::type_META)
- return false;
-
- return (dupli_type == BL::Object::dupli_type_VERTS ||
- dupli_type == BL::Object::dupli_type_FACES ||
- dupli_type == BL::Object::dupli_type_FRAMES);
-}
-
-static bool object_render_hide(BL::Object& b_ob,
- bool top_level,
- bool parent_hide,
- bool& hide_triangles)
-{
- /* check if we should render or hide particle emitter */
- BL::Object::particle_systems_iterator b_psys;
-
- bool hair_present = false;
- bool show_emitter = false;
- bool hide_emitter = false;
- bool hide_as_dupli_parent = false;
- bool hide_as_dupli_child_original = false;
-
- for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
- 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;
+ if(is_instance) {
+ /* Sync possible particle data. */
+ sync_dupli_particle(b_parent, b_instance, object);
}
- 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)
- hide_as_dupli_parent = true;
-
- /* hide original object for duplis */
- BL::Object parent = b_ob.parent();
- while(parent) {
- if(object_render_hide_original(b_ob.type(),
- parent.dupli_type()))
- {
- if(parent_hide) {
- hide_as_dupli_child_original = true;
- break;
- }
- }
- parent = parent.parent();
- }
-
- hide_triangles = hide_emitter;
-
- if(show_emitter) {
- return false;
- }
- else if(hair_present) {
- return hide_as_dupli_child_original;
- }
- else {
- return (hide_as_dupli_parent || hide_as_dupli_child_original);
- }
-}
-
-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()));
+ return object;
}
/* 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) {
@@ -564,100 +531,41 @@ 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_data, 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::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
- /* 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);
- }
- }
+ BL::Depsgraph::object_instances_iterator b_instance_iter;
+ for(b_depsgraph.object_instances.begin(b_instance_iter);
+ b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
+ ++b_instance_iter)
+ {
+ BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
+ BL::Object b_ob = b_instance.object();
- cancel = progress.get_cancel();
- }
+ progress.set_sync_status("Synchronizing object", b_ob.name());
+
+ /* load per-object culling data */
+ culling.init_object(scene, b_ob);
+
+ /* test if object needs to be hidden */
+ const bool show_self = b_instance.show_self();
+ const bool show_particles = b_instance.show_particles();
+
+ if(show_self || show_particles) {
+ /* object itself */
+ sync_object(b_depsgraph,
+ b_view_layer,
+ b_instance,
+ motion_time,
+ show_self,
+ show_particles,
+ culling,
+ &use_portal);
+ }
+
+ cancel = progress.get_cancel();
}
progress.set_sync_status("");
@@ -681,6 +589,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)
@@ -710,6 +619,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;
@@ -717,7 +627,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 */
@@ -756,7 +666,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 727d9acf729..a733a499826 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -28,11 +28,11 @@ CCL_NAMESPACE_BEGIN
/* Utilities */
bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
- BL::DupliObject& b_dup,
+ BL::DepsgraphObjectInstance& b_instance,
Object *object)
{
/* test if this dupli was generated from a particle sytem */
- BL::ParticleSystem b_psys = b_dup.particle_system();
+ BL::ParticleSystem b_psys = b_instance.particle_system();
if(!b_psys)
return false;
@@ -43,7 +43,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
return false;
/* don't handle child particles yet */
- BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup.persistent_id();
+ BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_instance.persistent_id();
if(persistent_id[0] >= b_psys.particles.length())
return false;
@@ -53,7 +53,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
ParticleSystem *psys;
bool first_use = !particle_system_map.is_used(key);
- bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key);
+ bool need_update = particle_system_map.sync(&psys, b_ob, b_instance.object(), key);
/* no update needed? */
if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 9dd0cd4c0bc..d111a1c1f1d 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;
@@ -218,17 +218,13 @@ static PyObject *create_func(PyObject * /*self*/, PyObject *args)
BL::RenderEngine engine(engineptr);
PointerRNA userprefptr;
- RNA_pointer_create(NULL, &RNA_UserPreferences, (void*)PyLong_AsVoidPtr(pyuserpref), &userprefptr);
- BL::UserPreferences userpref(userprefptr);
+ RNA_pointer_create(NULL, &RNA_Preferences, (void*)PyLong_AsVoidPtr(pyuserpref), &userprefptr);
+ BL::Preferences userpref(userprefptr);
PointerRNA dataptr;
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), &regionptr);
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);
@@ -768,10 +772,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, ""},
@@ -806,7 +810,7 @@ static struct PyModuleDef module = {
"Blender cycles render integration",
-1,
methods,
- NULL, NULL, NULL, NULL
+ NULL, NULL, NULL, NULL,
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 50ac35069a9..6e6d98b19dd 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -30,6 +30,7 @@
#include "render/shader.h"
#include "render/stats.h"
+#include "util/util_algorithm.h"
#include "util/util_color.h"
#include "util/util_foreach.h"
#include "util/util_function.h"
@@ -53,23 +54,25 @@ int BlenderSession::end_resumable_chunk = 0;
bool BlenderSession::print_render_stats = false;
BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
- BL::UserPreferences& b_userpref,
+ BL::Preferences& b_userpref,
BL::BlendData& b_data,
- BL::Scene& b_scene)
-: b_engine(b_engine),
+ bool preview_osl)
+: session(NULL),
+ sync(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;
@@ -77,25 +80,27 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
}
BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
- BL::UserPreferences& b_userpref,
+ BL::Preferences& 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),
+ sync(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;
@@ -133,6 +138,7 @@ void BlenderSession::create_session()
/* create scene */
scene = new Scene(scene_params, session->device);
+ scene->name = b_scene.name();
/* setup callbacks for builtin image support */
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3);
@@ -141,26 +147,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 +172,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)
@@ -192,11 +213,8 @@ void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_)
/* if scene or session parameters changed, it's easier to simply re-create
* them rather than trying to distinguish which settings need to be updated
*/
-
- delete session;
-
+ free_session();
create_session();
-
return;
}
@@ -210,16 +228,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,
@@ -379,8 +393,10 @@ static void add_cryptomatte_layer(BL::RenderResult& b_rr, string name, string ma
render_add_metadata(b_rr, prefix+"manifest", manifest);
}
-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);
@@ -390,131 +406,114 @@ 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);
+ const bool is_single_layer = (b_scene.view_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();
-
- /* 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;
+ b_rlay_name = b_view_layer.name();
+
+ /* add passes */
+ vector<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 full_denoising = get_boolean(crl, "use_denoising");
+ bool write_denoising_passes = get_boolean(crl, "denoising_store_passes");
+
+ bool run_denoising = full_denoising || write_denoising_passes;
+
+ session->tile_manager.schedule_denoising = run_denoising;
+ buffer_params.denoising_data_pass = run_denoising;
+ buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
+ buffer_params.denoising_prefiltered_pass = write_denoising_passes;
+
+ session->params.run_denoising = run_denoising;
+ session->params.full_denoising = full_denoising;
+ session->params.write_denoising_passes = write_denoising_passes;
+ 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->denoising_data_pass = buffer_params.denoising_data_pass;
+ scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
+ scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_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);
- /* 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;
- }
+ BL::RenderResult::views_iterator b_view_iter;
- BL::RenderLayer b_rlay = *b_single_rlay;
-
- /* add passes */
- vector<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 full_denoising = get_boolean(crl, "use_denoising");
- bool write_denoising_passes = get_boolean(crl, "denoising_store_passes");
-
- bool run_denoising = full_denoising || write_denoising_passes;
-
- session->tile_manager.schedule_denoising = run_denoising;
- buffer_params.denoising_data_pass = run_denoising;
- buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
- buffer_params.denoising_prefiltered_pass = write_denoising_passes;
-
- session->params.run_denoising = run_denoising;
- session->params.full_denoising = full_denoising;
- session->params.write_denoising_passes = write_denoising_passes;
- 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->denoising_data_pass = buffer_params.denoising_data_pass;
- scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
- scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_pass;
- 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);
- }
+ int num_views = 0;
+ for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
+ num_views++;
+ }
- /* Update number of samples per layer. */
- int samples = sync->get_layer_samples();
- bool bound_samples = sync->get_layer_bound_samples();
- int effective_layer_samples;
+ 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();
- if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
- effective_layer_samples = samples;
- else
- effective_layer_samples = session_params.samples;
+ /* set the current view */
+ b_engine.active_view_set(b_rview_name.c_str());
- /* Update tile manager if we're doing resumable render. */
- update_resumable_tile_manager(effective_layer_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);
+ builtin_images_load();
+
+ /* Attempt to free all data which is held by Blender side, since at this
+ * point we knwo that we've got everything to render current view layer.
+ */
+ /* At the moment we only free if we are not doing multi-view (or if we are rendering the last view).
+ * See T58142/D4239 for discussion.
+ */
+ if(view_index == num_views - 1) {
+ free_blender_memory_if_possible();
+ }
- /* Update session itself. */
- session->reset(buffer_params, 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);
+ }
- /* render */
- session->start();
- session->wait();
+ /* Update number of samples per layer. */
+ int samples = sync->get_layer_samples();
+ bool bound_samples = sync->get_layer_bound_samples();
+ int effective_layer_samples;
- if(session->progress.get_cancel())
- break;
- }
+ if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
+ effective_layer_samples = samples;
+ else
+ effective_layer_samples = session_params.samples;
- BL::RenderResult b_full_rr = b_engine.get_result();
- if(is_single_layer) {
- string num_aa_samples = string_printf("%d", session->params.samples);
- render_add_metadata(b_full_rr, "Cycles Samples", num_aa_samples);
- /* TODO(sergey): Report whether we're doing resumable render
- * and also start/end sample if so.
- */
- }
+ /* Update tile manager if we're doing resumable render. */
+ update_resumable_tile_manager(effective_layer_samples);
- if(scene->film->cryptomatte_passes & CRYPT_OBJECT) {
- add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoObject",
- scene->object_manager->get_cryptomatte_objects(scene));
- }
- if(scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
- add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoMaterial",
- scene->shader_manager->get_cryptomatte_materials(scene));
- }
- if(scene->film->cryptomatte_passes & CRYPT_ASSET) {
- add_cryptomatte_layer(b_full_rr, b_rlay_name+".CryptoAsset",
- scene->object_manager->get_cryptomatte_assets(scene));
- }
+ /* 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(!b_engine.is_preview() && background && print_render_stats) {
RenderStats stats;
@@ -526,6 +525,32 @@ void BlenderSession::render()
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.
+ */
+ }
+
+ /* Write cryptomatte metadata. */
+ if(scene->film->cryptomatte_passes & CRYPT_OBJECT) {
+ add_cryptomatte_layer(b_rr, b_rlay_name+".CryptoObject",
+ scene->object_manager->get_cryptomatte_objects(scene));
+ }
+ if(scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
+ add_cryptomatte_layer(b_rr, b_rlay_name+".CryptoMaterial",
+ scene->shader_manager->get_cryptomatte_materials(scene));
+ }
+ if(scene->film->cryptomatte_passes & CRYPT_ASSET) {
+ add_cryptomatte_layer(b_rr, b_rlay_name+".CryptoAsset",
+ scene->object_manager->get_cryptomatte_assets(scene));
+ }
+
+ /* 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;
@@ -535,6 +560,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
*/
@@ -543,6 +570,7 @@ void BlenderSession::render()
delete sync;
sync = NULL;
+#endif
}
static void populate_bake_data(BakeData *data, const
@@ -591,7 +619,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,
@@ -600,6 +629,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
@@ -632,11 +663,12 @@ 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_v3d,
- b_camera_override,
- width, height,
- &python_thread_state,
- b_rlay_name.c_str());
+ b_depsgraph,
+ b_v3d,
+ b_camera_override,
+ width, height,
+ &python_thread_state);
+ builtin_images_load();
}
BakeData *bake_data = NULL;
@@ -665,10 +697,14 @@ void BlenderSession::bake(BL::Object& b_object,
}
}
- int object = object_index;
+ /* Object might have been disabled for rendering or excluded in some
+ * other way, in that case Blender will report a warning afterwards. */
+ if (object_index != OBJECT_NONE) {
+ int object = object_index;
- bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
- populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
+ bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
+ populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
+ }
/* set number of samples */
session->tile_manager.set_samples(session_params.samples);
@@ -679,7 +715,7 @@ void BlenderSession::bake(BL::Object& b_object,
}
/* Perform bake. Check cancel to avoid crash with incomplete scene data. */
- if(!session->progress.get_cancel()) {
+ if(!session->progress.get_cancel() && bake_data) {
scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_pass_filter, bake_data, result);
}
@@ -770,7 +806,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)
@@ -795,7 +831,7 @@ void BlenderSession::synchronize()
/* copy recalc flags, outside of mutex so we can decide to do the real
* synchronization at a later time to not block on running updates */
- sync->sync_recalc();
+ sync->sync_recalc(b_depsgraph_);
/* don't do synchronization if on pause */
if(session_pause) {
@@ -810,19 +846,23 @@ 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);
else
sync->sync_camera(b_render, b_camera_override, width, height, "");
+ builtin_images_load();
+
/* unlock */
session->scene->mutex.unlock();
@@ -939,7 +979,7 @@ void BlenderSession::update_bake_progress()
void BlenderSession::update_status_progress()
{
string timestatus, status, substatus;
- string scene = "";
+ string scene_status = "";
float progress;
double total_time, remaining_time = 0, render_time;
char time_str[128];
@@ -953,35 +993,31 @@ void BlenderSession::update_status_progress()
remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
if(background) {
- scene += " | " + b_scene.name();
+ scene_status += " | " + scene->name;
if(b_rlay_name != "")
- scene += ", " + b_rlay_name;
+ scene_status += ", " + b_rlay_name;
if(b_rview_name != "")
- scene += ", " + b_rview_name;
- }
- else {
- BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), total_time);
- timestatus = "Time:" + string(time_str) + " | ";
- }
+ scene_status += ", " + b_rview_name;
- if(remaining_time > 0) {
- BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), remaining_time);
- timestatus += "Remaining:" + string(time_str) + " | ";
- }
+ if(remaining_time > 0) {
+ BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), remaining_time);
+ timestatus += "Remaining:" + string(time_str) + " | ";
+ }
- timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
+ timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
- if(status.size() > 0)
- status = " | " + status;
- if(substatus.size() > 0)
- status += " | " + substatus;
+ if(status.size() > 0)
+ status = " | " + status;
+ if(substatus.size() > 0)
+ status += " | " + substatus;
+ }
double current_time = time_dt();
/* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date.
* For headless rendering, only report when something significant changes to keep the console output readable. */
if(status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
- b_engine.update_stats("", (timestatus + scene + status).c_str());
+ b_engine.update_stats("", (timestatus + scene_status + status).c_str());
b_engine.update_memory_stats(mem_used, mem_peak);
last_status = status;
last_status_time = current_time;
@@ -1334,6 +1370,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);
@@ -1341,14 +1380,23 @@ 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);
}
}
return false;
}
+void BlenderSession::builtin_images_load()
+{
+ /* Force builtin images to be loaded along with Blender data sync. This
+ * is needed because we may be reading from depsgraph evaluated data which
+ * can be freed by Blender before Cycles reads it. */
+ ImageManager *manager = session->scene->image_manager;
+ Device *device = session->device;
+ manager->device_load_builtin(device, session->scene, session->progress);
+}
+
void BlenderSession::update_resumable_tile_manager(int num_samples)
{
const int num_resumable_chunks = BlenderSession::num_resumable_chunks,
@@ -1357,9 +1405,15 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
return;
}
- const int num_samples_per_chunk = (int)ceilf((float)num_samples / num_resumable_chunks);
+ if (num_resumable_chunks > num_samples) {
+ fprintf(stderr, "Cycles warning: more sample chunks (%d) than samples (%d), "
+ "this will cause some samples to be included in multiple chunks.\n",
+ num_resumable_chunks, num_samples);
+ }
+
+ const float num_samples_per_chunk = (float)num_samples / num_resumable_chunks;
- int range_start_sample, range_num_samples;
+ float range_start_sample, range_num_samples;
if(current_resumable_chunk != 0) {
/* Single chunk rendering. */
range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
@@ -1371,19 +1425,37 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
range_num_samples = num_chunks * num_samples_per_chunk;
}
+
+ /* Round after doing the multiplications with num_chunks and num_samples_per_chunk
+ * to allow for many small chunks. */
+ int rounded_range_start_sample = (int)floor(range_start_sample + 0.5f);
+ int rounded_range_num_samples = max((int)floor(range_num_samples + 0.5f), 1);
+
/* Make sure we don't overshoot. */
- if(range_start_sample + range_num_samples > num_samples) {
- range_num_samples = num_samples - range_num_samples;
+ if(rounded_range_start_sample + rounded_range_num_samples > num_samples) {
+ rounded_range_num_samples = num_samples - rounded_range_num_samples;
}
VLOG(1) << "Samples range start is " << range_start_sample << ", "
<< "number of samples to render is " << range_num_samples;
- scene->integrator->start_sample = range_start_sample;
+ scene->integrator->start_sample = rounded_range_start_sample;
scene->integrator->tag_update(scene);
- session->tile_manager.range_start_sample = range_start_sample;
- session->tile_manager.range_num_samples = range_num_samples;
+ session->tile_manager.range_start_sample = rounded_range_start_sample;
+ session->tile_manager.range_num_samples = rounded_range_num_samples;
+}
+
+void BlenderSession::free_blender_memory_if_possible()
+{
+ if(!background) {
+ /* During interactive render we can not free anything: attempts to save
+ * memory would cause things to be allocated and evaluated for every
+ * updated sample.
+ */
+ return;
+ }
+ b_engine.free_blender_memory();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index b8a9096b354..96ffc06a3db 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -35,14 +35,13 @@ class RenderTile;
class BlenderSession {
public:
BlenderSession(BL::RenderEngine& b_engine,
- BL::UserPreferences& b_userpref,
+ BL::Preferences& b_userpref,
BL::BlendData& b_data,
- BL::Scene& b_scene);
+ bool preview_osl);
BlenderSession(BL::RenderEngine& b_engine,
- BL::UserPreferences& b_userpref,
+ BL::Preferences& 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);
@@ -102,9 +102,13 @@ public:
double last_redraw_time;
BL::RenderEngine b_engine;
- BL::UserPreferences b_userpref;
+ BL::Preferences b_userpref;
BL::BlendData b_data;
BL::RenderSettings b_render;
+ BL::Depsgraph b_depsgraph;
+ /* NOTE: Blender's scene might become invalid after call
+ * free_blender_memory_if_possible().
+ */
BL::Scene b_scene;
BL::SpaceView3D b_v3d;
BL::RegionView3D b_rv3d;
@@ -117,6 +121,7 @@ public:
double last_status_time;
int width, height;
+ bool preview_osl;
double start_resize_time;
void *python_thread_state;
@@ -166,9 +171,16 @@ protected:
float *pixels,
const size_t pixels_size,
const bool free_cache);
+ void builtin_images_load();
/* Update tile manager to reflect resumable render settings. */
void update_resumable_tile_manager(int num_samples);
+
+ /* Is used after each render layer synchronization is done with the goal
+ * of freeing render engine data which is held from Blender side (for
+ * example, dependency graph).
+ */
+ void free_blender_memory_if_possible();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index e33a6c20a52..b04a0394141 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)
@@ -677,7 +670,9 @@ static ShaderNode *add_node(Scene *scene,
image->animated = b_image_node.image_user().use_auto_refresh();
image->use_alpha = b_image.use_alpha();
+ /* TODO: restore */
/* TODO(sergey): Does not work properly when we change builtin type. */
+#if 0
if(b_image.is_updated()) {
scene->image_manager->tag_reload_image(
image->filename.string(),
@@ -686,6 +681,7 @@ static ShaderNode *add_node(Scene *scene,
get_image_extension(b_image_node),
image->use_alpha);
}
+#endif
}
image->color_space = (NodeImageColorSpace)b_image_node.color_space();
image->projection = (NodeImageProjection)b_image_node.projection();
@@ -725,7 +721,9 @@ static ShaderNode *add_node(Scene *scene,
env->animated = b_env_node.image_user().use_auto_refresh();
env->use_alpha = b_image.use_alpha();
+ /* TODO: restore */
/* TODO(sergey): Does not work properly when we change builtin type. */
+#if 0
if(b_image.is_updated()) {
scene->image_manager->tag_reload_image(
env->filename.string(),
@@ -734,6 +732,7 @@ static ShaderNode *add_node(Scene *scene,
EXTENSION_REPEAT,
env->use_alpha);
}
+#endif
}
env->color_space = (NodeImageColorSpace)b_env_node.color_space();
env->interpolation = get_image_interpolation(b_env_node);
@@ -813,7 +812,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) {
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
- tex_coord->from_dupli = b_tex_coord_node.from_dupli();
+ tex_coord->from_dupli = b_tex_coord_node.from_instancer();
if(b_tex_coord_node.object()) {
tex_coord->use_transform = true;
tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
@@ -866,7 +865,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeUVMap b_uvmap_node(b_node);
UVMapNode *uvm = new UVMapNode();
uvm->attribute = b_uvmap_node.uv_map();
- uvm->from_dupli = b_uvmap_node.from_dupli();
+ uvm->from_dupli = b_uvmap_node.from_instancer();
node = uvm;
}
else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
@@ -876,13 +875,12 @@ static ShaderNode *add_node(Scene *scene,
point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
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;
+ point_density->image_manager = scene->image_manager;
/* TODO(sergey): Use more proper update flag. */
if(true) {
- b_point_density_node.cache_point_density(b_scene, settings);
+ point_density->add_image();
+ b_point_density_node.cache_point_density(b_depsgraph);
scene->image_manager->tag_reload_image(
point_density->filename.string(),
point_density->builtin_data,
@@ -900,9 +898,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 =
@@ -1015,8 +1012,8 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *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,
@@ -1031,23 +1028,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 = b_ntree.get_output_node(BL::ShaderNodeOutputMaterial::target_CYCLES);
/* add nodes */
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
@@ -1117,8 +1098,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,
@@ -1156,18 +1137,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);
@@ -1229,8 +1208,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)
{
@@ -1238,8 +1217,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,
@@ -1248,35 +1227,39 @@ 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) {
+ BL::Depsgraph::ids_iterator b_id;
+ for(b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
+ if(!b_id->is_a(&RNA_Material)) {
+ continue;
+ }
+
+ BL::Material b_mat(*b_id);
Shader *shader;
/* test if we need to sync */
- if(shader_map.sync(&shader, *b_mat) || update_all) {
+ if(shader_map.sync(&shader, b_mat) || shader->need_sync_object || update_all) {
ShaderGraph *graph = new ShaderGraph();
- shader->name = b_mat->name().c_str();
- shader->pass_id = b_mat->pass_index();
+ shader->name = b_mat.name().c_str();
+ shader->pass_id = b_mat.pass_index();
+ shader->need_sync_object = false;
/* create nodes */
- if(b_mat->use_nodes() && b_mat->node_tree()) {
- BL::ShaderNodeTree b_ntree(b_mat->node_tree());
+ 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();
- diffuse->color = get_float3(b_mat->diffuse_color());
+ diffuse->color = get_float3(b_mat.diffuse_color());
graph->add(diffuse);
ShaderNode *out = graph->output();
@@ -1284,7 +1267,7 @@ void BlenderSync::sync_materials(bool update_all)
}
/* settings */
- PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
+ PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
shader->use_mis = get_boolean(cmat, "sample_as_light");
shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
@@ -1328,7 +1311,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;
@@ -1343,7 +1326,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");
@@ -1353,7 +1336,7 @@ void BlenderSync::sync_world(bool update_all)
}
else if(b_world) {
BackgroundNode *background = new BackgroundNode();
- background->color = get_float3(b_world.horizon_color());
+ background->color = get_float3(b_world.color());
graph->add(background);
ShaderNode *out = graph->output();
@@ -1411,49 +1394,52 @@ 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);
}
-/* Sync Lamps */
+/* Sync Lights */
-void BlenderSync::sync_lamps(bool update_all)
+void BlenderSync::sync_lights(BL::Depsgraph& b_depsgraph, bool update_all)
{
shader_map.set_default(scene->default_light);
- /* lamp loop */
- BL::BlendData::lamps_iterator b_lamp;
+ BL::Depsgraph::ids_iterator b_id;
+ for(b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
+ if(!b_id->is_a(&RNA_Light)) {
+ continue;
+ }
- for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
+ BL::Light b_light(*b_id);
Shader *shader;
/* test if we need to sync */
- if(shader_map.sync(&shader, *b_lamp) || update_all) {
+ if(shader_map.sync(&shader, b_light) || update_all) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
- if(b_lamp->use_nodes() && b_lamp->node_tree()) {
- shader->name = b_lamp->name().c_str();
+ if(b_light.use_nodes() && b_light.node_tree()) {
+ shader->name = b_light.name().c_str();
- BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
+ BL::ShaderNodeTree b_ntree(b_light.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;
- if(b_lamp->type() == BL::Lamp::type_POINT ||
- b_lamp->type() == BL::Lamp::type_SPOT ||
- b_lamp->type() == BL::Lamp::type_AREA)
+ if(b_light.type() == BL::Light::type_POINT ||
+ b_light.type() == BL::Light::type_SPOT ||
+ b_light.type() == BL::Light::type_AREA)
{
strength = 100.0f;
}
EmissionNode *emission = new EmissionNode();
- emission->color = get_float3(b_lamp->color());
+ emission->color = get_float3(b_light.color());
emission->strength = strength;
graph->add(emission);
@@ -1467,7 +1453,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;
@@ -1480,9 +1466,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_lights(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 a6050b66040..072af281a73 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -78,31 +78,12 @@ BlenderSync::~BlenderSync()
/* Sync */
-bool BlenderSync::sync_recalc()
+void BlenderSync::sync_recalc(BL::Depsgraph& b_depsgraph)
{
- /* sync recalc flags from blender to cycles. actual update is done separate,
- * so we can do it later on if doing it immediate is not suitable */
-
- BL::BlendData::materials_iterator b_mat;
- bool has_updated_objects = b_data.objects.is_updated();
- for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
- if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) {
- shader_map.set_recalc(*b_mat);
- }
- else {
- Shader *shader = shader_map.find(*b_mat);
- if(has_updated_objects && shader != NULL && shader->has_object_dependency) {
- shader_map.set_recalc(*b_mat);
- }
- }
- }
-
- BL::BlendData::lamps_iterator b_lamp;
-
- for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
- if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
- shader_map.set_recalc(*b_lamp);
+ /* Sync recalc flags from blender to cycles. Actual update is done separate,
+ * so we can do it later on if doing it immediate is not suitable. */
+ bool has_updated_objects = b_depsgraph.id_type_updated(BL::DriverTarget::id_type_OBJECT);
bool dicing_prop_changed = false;
if(experimental) {
@@ -124,83 +105,92 @@ bool BlenderSync::sync_recalc()
}
}
- BL::BlendData::objects_iterator b_ob;
+ /* Iterate over all IDs in this depsgraph. */
+ BL::Depsgraph::updates_iterator b_update;
+ for(b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) {
+ BL::ID b_id(b_update->id());
- for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
- if(b_ob->is_updated()) {
- object_map.set_recalc(*b_ob);
- light_map.set_recalc(*b_ob);
+ /* Material */
+ if(b_id.is_a(&RNA_Material)) {
+ BL::Material b_mat(b_id);
+ shader_map.set_recalc(b_mat);
+ }
+ /* Light */
+ else if(b_id.is_a(&RNA_Light)) {
+ BL::Light b_light(b_id);
+ shader_map.set_recalc(b_light);
}
+ /* Object */
+ else if(b_id.is_a(&RNA_Object)) {
+ BL::Object b_ob(b_id);
+ const bool updated_geometry = b_update->is_updated_geometry();
+
+ if(b_update->is_updated_transform()) {
+ object_map.set_recalc(b_ob);
+ light_map.set_recalc(b_ob);
+ }
- if(object_is_mesh(*b_ob)) {
- if(b_ob->is_updated_data() || b_ob->data().is_updated() ||
- (dicing_prop_changed && object_subdivision_type(*b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
- {
- BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
- mesh_map.set_recalc(key);
+ if(object_is_mesh(b_ob)) {
+ if(updated_geometry ||
+ (dicing_prop_changed && object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
+ {
+ BL::ID key = BKE_object_is_modified(b_ob)? b_ob: b_ob.data();
+ mesh_map.set_recalc(key);
+ }
+ }
+ else if(object_is_light(b_ob)) {
+ if(updated_geometry) {
+ light_map.set_recalc(b_ob);
+ }
+ }
+
+ if(updated_geometry) {
+ BL::Object::particle_systems_iterator b_psys;
+ for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys)
+ particle_system_map.set_recalc(b_ob);
}
}
- else if(object_is_light(*b_ob)) {
- if(b_ob->is_updated_data() || b_ob->data().is_updated())
- light_map.set_recalc(*b_ob);
+ /* Mesh */
+ else if(b_id.is_a(&RNA_Mesh)) {
+ BL::Mesh b_mesh(b_id);
+ mesh_map.set_recalc(b_mesh);
}
-
- if(b_ob->is_updated_data()) {
- BL::Object::particle_systems_iterator b_psys;
- for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
- particle_system_map.set_recalc(*b_ob);
+ /* World */
+ else if(b_id.is_a(&RNA_World)) {
+ BL::World b_world(b_id);
+ if(world_map == b_world.ptr.data) {
+ world_recalc = true;
+ }
}
}
- BL::BlendData::meshes_iterator b_mesh;
-
- for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh) {
- if(b_mesh->is_updated()) {
- mesh_map.set_recalc(*b_mesh);
+ /* Updates shader with object dependency if objects changed. */
+ if(has_updated_objects) {
+ if(scene->default_background->has_object_dependency) {
+ world_recalc = true;
}
- }
- BL::BlendData::worlds_iterator b_world;
-
- for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
- if(world_map == b_world->ptr.data) {
- if(b_world->is_updated() ||
- (b_world->node_tree() && b_world->node_tree().is_updated()))
- {
- world_recalc = true;
- }
- else if(b_world->node_tree() && b_world->use_nodes()) {
- Shader *shader = scene->default_background;
- if(has_updated_objects && shader->has_object_dependency) {
- world_recalc = true;
- }
+ foreach(Shader *shader, scene->shaders) {
+ if(shader->has_object_dependency) {
+ shader->need_sync_object = true;
}
}
}
-
- bool recalc =
- shader_map.has_recalc() ||
- object_map.has_recalc() ||
- light_map.has_recalc() ||
- mesh_map.has_recalc() ||
- particle_system_map.has_recalc() ||
- BlendDataObjects_is_updated_get(&b_data.ptr) ||
- world_recalc;
-
- return 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();
@@ -210,14 +200,17 @@ 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);
mesh_synced.clear();
+
+ free_data_after_sync(b_depsgraph);
}
/* Integrator */
@@ -371,75 +364,33 @@ 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;
+ view_layer.name = b_view_layer.name();
+ 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();
+
+ /* Material override. */
+ view_layer.material_override = b_view_layer.material_override();
+
+ /* Sample override. */
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
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;
- }
- }
- first_layer = false;
+ view_layer.bound_samples = (use_layer_samples == 1);
+ view_layer.samples = 0;
+
+ if(use_layer_samples != 2) {
+ int samples = b_view_layer.samples();
+ if(get_boolean(cscene, "use_square_samples"))
+ view_layer.samples = samples * samples;
+ else
+ view_layer.samples = samples;
}
+
}
/* Images */
@@ -552,7 +503,7 @@ int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass)
}
vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
- BL::SceneRenderLayer& b_srlay,
+ BL::ViewLayer& b_view_layer,
const SessionParams &session_params)
{
vector<Pass> passes;
@@ -575,7 +526,7 @@ vector<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");
bool full_denoising = get_boolean(crp, "use_denoising");
bool write_denoising_passes = get_boolean(crp, "denoising_store_passes");
@@ -591,49 +542,49 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
MAP_OPTION("denoising_subsurface_direct", DENOISING_CLEAN_SUBSURFACE_DIR);
MAP_OPTION("denoising_subsurface_indirect", DENOISING_CLEAN_SUBSURFACE_IND);
#undef MAP_OPTION
- b_engine.add_pass("Noisy Image", 4, "RGBA", b_srlay.name().c_str());
+ b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
}
if(write_denoising_passes) {
- b_engine.add_pass("Denoising Normal", 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 Depth", 1, "Z", b_srlay.name().c_str());
- b_engine.add_pass("Denoising Shadowing", 1, "X", b_srlay.name().c_str());
- b_engine.add_pass("Denoising Variance", 3, "RGB", b_srlay.name().c_str());
- b_engine.add_pass("Denoising Intensity", 1, "X", b_srlay.name().c_str());
+ b_engine.add_pass("Denoising Normal", 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 Depth", 1, "Z", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Shadowing", 1, "X", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Variance", 3, "RGB", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str());
if(scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) {
- b_engine.add_pass("Denoising Clean", 3, "RGB", b_srlay.name().c_str());
+ b_engine.add_pass("Denoising Clean", 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);
}
@@ -645,7 +596,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
if(get_boolean(crp, "use_pass_crypto_object")) {
for(int i = 0; i < crypto_depth; ++i) {
string passname = cryptomatte_prefix + string_printf("Object%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str());
+ b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_OBJECT);
@@ -653,7 +604,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
if(get_boolean(crp, "use_pass_crypto_material")) {
for(int i = 0; i < crypto_depth; ++i) {
string passname = cryptomatte_prefix + string_printf("Material%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str());
+ b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_MATERIAL);
@@ -661,7 +612,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
if(get_boolean(crp, "use_pass_crypto_asset")) {
for(int i = 0; i < crypto_depth; ++i) {
string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str());
+ b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_ASSET);
@@ -673,6 +624,30 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
return passes;
}
+void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph)
+{
+ /* When viewport display is not needed during render we can force some
+ * caches to be releases from blender side in order to reduce peak memory
+ * footprint during synchronization process.
+ */
+ const bool is_interface_locked = b_engine.render() &&
+ b_engine.render().use_lock_interface();
+ const bool can_free_caches = BlenderSession::headless || is_interface_locked;
+ if(!can_free_caches) {
+ return;
+ }
+ /* TODO(sergey): We can actually remove the whole dependency graph,
+ * but that will need some API support first.
+ */
+ BL::Depsgraph::objects_iterator b_ob;
+ for(b_depsgraph.objects.begin(b_ob);
+ b_ob != b_depsgraph.objects.end();
+ ++b_ob)
+ {
+ b_ob->cache_release();
+ }
+}
+
/* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
@@ -741,7 +716,7 @@ bool BlenderSync::get_session_pause(BL::Scene& b_scene, bool background)
}
SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
- BL::UserPreferences& b_userpref,
+ BL::Preferences& b_userpref,
BL::Scene& b_scene,
bool background)
{
@@ -775,7 +750,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
/* Find cycles preferences. */
PointerRNA b_preferences;
- BL::UserPreferences::addons_iterator b_addon_iter;
+ BL::Preferences::addons_iterator b_addon_iter;
for(b_userpref.addons.begin(b_addon_iter); b_addon_iter != b_userpref.addons.end(); ++b_addon_iter) {
if(b_addon_iter->module() == "cycles") {
b_preferences = b_addon_iter->preferences().ptr;
@@ -900,13 +875,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;
}
@@ -934,17 +910,7 @@ 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 = 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 6d78f62c7d0..bf16de4a9c9 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;
@@ -58,16 +59,16 @@ public:
~BlenderSync();
/* sync */
- bool sync_recalc();
+ void sync_recalc(BL::Depsgraph& b_depsgraph);
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);
- vector<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);
+ vector<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,14 +78,14 @@ 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,
bool background);
static SessionParams get_session_params(BL::RenderEngine& b_engine,
- BL::UserPreferences& b_userpref,
+ BL::Preferences& b_userpref,
BL::Scene& b_scene,
bool background);
static bool get_session_pause(BL::Scene& b_scene, bool background);
@@ -99,43 +100,50 @@ 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_lights(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 show_self,
+ bool show_particles);
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,
- uint layer_flag,
+ Object *sync_object(BL::Depsgraph& b_depsgraph,
+ BL::ViewLayer& b_view_layer,
+ BL::DepsgraphObjectInstance& b_instance,
float motion_time,
- bool hide_tris,
+ bool show_self,
+ bool show_particles,
BlenderObjectCulling& culling,
bool *use_portal);
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,12 +153,15 @@ private:
/* particles */
bool sync_dupli_particle(BL::Object& b_ob,
- BL::DupliObject& b_dup,
+ BL::DepsgraphObjectInstance& b_instance,
Object *object);
/* Images. */
void sync_images();
+ /* Early data free. */
+ void free_data_after_sync(BL::Depsgraph& b_depsgraph);
+
/* util */
void find_shader(BL::ID& id, vector<Shader*>& used_shaders, Shader *default_shader);
bool BKE_object_is_modified(BL::Object& b_ob);
@@ -182,31 +193,24 @@ private:
struct RenderLayerInfo {
RenderLayerInfo()
- : scene_layer(0), layer(0),
- holdout_layer(0), exclude_layer(0),
- material_override(PointerRNA_NULL),
+ : 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)
+ samples(0),
+ bound_samples(false)
{}
string name;
- uint scene_layer;
- uint layer;
- uint holdout_layer;
- uint exclude_layer;
BL::Material material_override;
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;
+ } 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 eb7019f45bc..1b9e1911591 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -33,7 +33,7 @@
extern "C" {
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxlen, double time_seconds);
-void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
+void BKE_image_user_frame_calc(void *iuser, int cfra);
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
@@ -46,12 +46,12 @@ 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,
- bool apply_modifiers,
- bool render,
+ BL::Depsgraph& depsgraph,
bool calc_undeformed,
Mesh::SubdivisionType subdivision_type)
{
+ /* TODO: make this work with copy-on-write, modifiers are already evaluated. */
+#if 0
bool subsurf_mod_show_render = false;
bool subsurf_mod_show_viewport = false;
@@ -64,30 +64,54 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
subsurf_mod.show_render(false);
subsurf_mod.show_viewport(false);
}
+#endif
- BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
+ BL::Mesh mesh(PointerRNA_NULL);
+ if(object.type() == BL::Object::type_MESH) {
+ /* TODO: calc_undeformed is not used. */
+ mesh = BL::Mesh(object.data());
+ /* Make a copy to split faces if we use autosmooth, otherwise not needed.
+ * Also in edit mode do we need to make a copy, to ensure data layers like
+ * UV are not empty. */
+ if (mesh.is_editmode() ||
+ (mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE))
+ {
+ mesh = data.meshes.new_from_object(depsgraph, object, false, false);
+ }
+ }
+ else {
+ mesh = data.meshes.new_from_object(depsgraph, object, true, calc_undeformed);
+ }
+
+#if 0
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
subsurf_mod.show_render(subsurf_mod_show_render);
subsurf_mod.show_viewport(subsurf_mod_show_viewport);
}
+#endif
- if((bool)me) {
- if(me.use_auto_smooth()) {
- if(subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK) {
- me.calc_normals_split();
- }
- else {
- me.split_faces(false);
- }
- }
- if(subdivision_type == Mesh::SUBDIVISION_NONE) {
- me.calc_tessface(true);
+ if((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) {
+ if(mesh.use_auto_smooth()) {
+ mesh.split_faces(false);
}
+
+ mesh.calc_loop_triangles();
+ }
+
+ return mesh;
+}
+
+static inline void free_object_to_mesh(BL::BlendData& data,
+ BL::Object& object,
+ BL::Mesh& mesh)
+{
+ /* Free mesh if we didn't just use the existing one. */
+ if(object.data().ptr.data != mesh.ptr.data) {
+ data.meshes.remove(mesh, false, true, false);
}
- return me;
}
static inline void colorramp_to_array(BL::ColorRamp& ramp,
@@ -221,14 +245,14 @@ static inline string image_user_file_path(BL::ImageUser& iuser,
int cfra)
{
char filepath[1024];
- BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
+ BKE_image_user_frame_calc(iuser.ptr.data, cfra);
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
return string(filepath);
}
static inline int image_user_frame_number(BL::ImageUser& iuser, int cfra)
{
- BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
+ BKE_image_user_frame_calc(iuser.ptr.data, cfra);
return iuser.frame_current();
}
@@ -314,7 +338,7 @@ static inline uint get_layer(const BL::Array<bool, 20>& array)
static inline uint get_layer(const BL::Array<bool, 20>& array,
const BL::Array<bool, 8>& local_array,
bool is_light = false,
- uint scene_layers = (1 << 20) - 1)
+ uint view_layers = (1 << 20) - 1)
{
uint layer = 0;
@@ -326,7 +350,7 @@ static inline uint get_layer(const BL::Array<bool, 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));
}