[Bf-blender-cvs] [ad35453cd19] master: Cycles: Add support for light groups

Lukas Stockner noreply at git.blender.org
Sat Apr 2 06:17:07 CEST 2022


Commit: ad35453cd19b3db779b0b3a90feac2e93c7a73cf
Author: Lukas Stockner
Date:   Sat Apr 2 00:11:11 2022 +0200
Branches: master
https://developer.blender.org/rBad35453cd19b3db779b0b3a90feac2e93c7a73cf

Cycles: Add support for light groups

Light groups are a type of pass that only contains lighting from a subset of light sources.
They are created in the View layer, and light sources (lamps, objects with emissive materials
and/or the environment) can be assigned to a group.

Currently, each light group ends up generating its own version of the Combined pass.
In the future, additional types of passes (e.g. shadowcatcher) might be getting their own
per-lightgroup versions.

The lightgroup creation and assignment is not Cycles-specific, so Eevee or external render
engines could make use of it in the future.

Note that Lightgroups are identified by their name - therefore, the name of the Lightgroup
in the View Layer and the name that's set in an object's settings must match for it to be
included.
Currently, changing a Lightgroup's name does not update objects - this is planned for the
future, along with other features such as denoising for light groups and viewing them in
preview renders.

Original patch by Alex Fuller (@mistaed), with some polishing by Lukas Stockner (@lukasstockner97).

Differential Revision: https://developer.blender.org/D12871

===================================================================

M	intern/cycles/blender/addon/engine.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/light.cpp
M	intern/cycles/blender/object.cpp
M	intern/cycles/blender/shader.cpp
M	intern/cycles/blender/sync.cpp
M	intern/cycles/integrator/pass_accessor.cpp
M	intern/cycles/integrator/pass_accessor.h
M	intern/cycles/kernel/film/accumulate.h
M	intern/cycles/kernel/geom/object.h
M	intern/cycles/kernel/integrator/shade_background.h
M	intern/cycles/kernel/integrator/shade_light.h
M	intern/cycles/kernel/integrator/shade_surface.h
M	intern/cycles/kernel/integrator/shade_volume.h
M	intern/cycles/kernel/integrator/shadow_state_template.h
M	intern/cycles/kernel/light/light.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/background.cpp
M	intern/cycles/scene/background.h
M	intern/cycles/scene/film.cpp
M	intern/cycles/scene/film.h
M	intern/cycles/scene/light.cpp
M	intern/cycles/scene/light.h
M	intern/cycles/scene/object.cpp
M	intern/cycles/scene/object.h
M	intern/cycles/scene/pass.cpp
M	intern/cycles/scene/pass.h
M	intern/cycles/scene/scene.cpp
M	intern/cycles/scene/scene.h
M	intern/cycles/session/buffers.cpp
M	intern/cycles/session/buffers.h
M	release/scripts/startup/bl_ui/properties_view_layer.py
M	source/blender/blenkernel/BKE_layer.h
M	source/blender/blenkernel/intern/layer.c
M	source/blender/blenkernel/intern/object.cc
M	source/blender/blenkernel/intern/world.c
M	source/blender/editors/render/render_intern.hh
M	source/blender/editors/render/render_ops.cc
M	source/blender/editors/render/render_shading.cc
M	source/blender/makesdna/DNA_layer_types.h
M	source/blender/makesdna/DNA_object_types.h
M	source/blender/makesdna/DNA_world_types.h
M	source/blender/makesrna/intern/rna_internal.h
M	source/blender/makesrna/intern/rna_object.c
M	source/blender/makesrna/intern/rna_scene.c
M	source/blender/makesrna/intern/rna_world.c

===================================================================

diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 48dd26cc622..b7713dc7110 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -228,6 +228,10 @@ def list_render_passes(scene, srl):
         else:
             yield (aov.name, "RGB", 'COLOR')
 
+    # Light groups.
+    for lightgroup in srl.lightgroups:
+        yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
+
 
 def register_passes(engine, scene, view_layer):
     for name, channelids, channeltype in list_render_passes(scene, view_layer):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index c86452e0a18..621a5571f63 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -12,7 +12,7 @@ from bpy.types import Panel
 
 from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
 from bl_ui.properties_render import draw_hair_settings
-from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel
+from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel, ViewLayerLightgroupsPanel
 
 class CyclesPresetPanel(PresetPanel, Panel):
     COMPAT_ENGINES = {'CYCLES'}
@@ -883,6 +883,12 @@ class CYCLES_RENDER_PT_passes_aov(CyclesButtonsPanel, ViewLayerAOVPanel):
     bl_parent_id = "CYCLES_RENDER_PT_passes"
 
 
+class CYCLES_RENDER_PT_passes_lightgroups(CyclesButtonsPanel, ViewLayerLightgroupsPanel):
+    bl_label = "Light Groups"
+    bl_context = "view_layer"
+    bl_parent_id = "CYCLES_RENDER_PT_passes"
+
+
 class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
     bl_label = "Post Processing"
     bl_options = {'DEFAULT_CLOSED'}
@@ -1147,6 +1153,23 @@ class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel):
         col.prop(cob, "is_caustics_receiver")
 
 
+class CYCLES_OBJECT_PT_lightgroup(CyclesButtonsPanel, Panel):
+    bl_label = "Light Group"
+    bl_parent_id = "CYCLES_OBJECT_PT_shading"
+    bl_context = "object"
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+
+        ob = context.object
+
+        view_layer = context.view_layer
+
+        col = layout.column(align=True)
+        col.prop_search(ob, "lightgroup", view_layer, "lightgroups", text="Light Group")
+
+
 class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
     bl_label = "Visibility"
     bl_context = "object"
@@ -1399,10 +1422,14 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
         layout.use_property_split = True
 
         world = context.world
+        view_layer = context.view_layer
 
         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
             layout.prop(world, "color")
 
+        col = layout.column(align=True)
+        col.prop_search(world, "lightgroup", view_layer, "lightgroups", text="Light Group")
+
 
 class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
     bl_label = "Volume"
@@ -2209,6 +2236,7 @@ classes = (
     CYCLES_RENDER_PT_passes_light,
     CYCLES_RENDER_PT_passes_crypto,
     CYCLES_RENDER_PT_passes_aov,
+    CYCLES_RENDER_PT_passes_lightgroups,
     CYCLES_RENDER_PT_filter,
     CYCLES_RENDER_PT_override,
     CYCLES_PT_post_processing,
@@ -2220,6 +2248,7 @@ classes = (
     CYCLES_OBJECT_PT_shading_shadow_terminator,
     CYCLES_OBJECT_PT_shading_gi_approximation,
     CYCLES_OBJECT_PT_shading_caustics,
+    CYCLES_OBJECT_PT_lightgroup,
     CYCLES_OBJECT_PT_visibility,
     CYCLES_OBJECT_PT_visibility_ray_visibility,
     CYCLES_OBJECT_PT_visibility_culling,
diff --git a/intern/cycles/blender/light.cpp b/intern/cycles/blender/light.cpp
index 04799443ceb..5359fa13505 100644
--- a/intern/cycles/blender/light.cpp
+++ b/intern/cycles/blender/light.cpp
@@ -143,6 +143,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
   light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
   light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
 
+  /* lightgroup */
+  light->set_lightgroup(ustring(b_ob_info.real_object.lightgroup()));
+
   /* tag */
   light->tag_update(scene);
 }
diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp
index 16a6b3454ed..d8f236e0641 100644
--- a/intern/cycles/blender/object.cpp
+++ b/intern/cycles/blender/object.cpp
@@ -343,6 +343,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
       object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0));
     }
 
+    /* lightgroup */
+    object->set_lightgroup(ustring(b_ob.lightgroup()));
+
     object->tag_update(scene);
   }
 
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index 224cbea85f3..d3527567b96 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -1532,6 +1532,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
   background->set_use_shader(view_layer.use_background_shader ||
                              viewport_parameters.use_custom_shader());
 
+  background->set_lightgroup(ustring(b_world ? b_world.lightgroup() : ""));
+
   background->tag_update(scene);
 }
 
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index 8af2ee7a435..bd6bfafedeb 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -745,6 +745,20 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
     }
   }
 
+  /* Light Group passes. */
+  BL::ViewLayer::lightgroups_iterator b_lightgroup_iter;
+  for (b_view_layer.lightgroups.begin(b_lightgroup_iter);
+       b_lightgroup_iter != b_view_layer.lightgroups.end();
+       ++b_lightgroup_iter) {
+    BL::Lightgroup b_lightgroup(*b_lightgroup_iter);
+
+    string name = string_printf("Combined_%s", b_lightgroup.name().c_str());
+
+    b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str());
+    Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY);
+    pass->set_lightgroup(ustring(b_lightgroup.name()));
+  }
+
   scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
 }
 
diff --git a/intern/cycles/integrator/pass_accessor.cpp b/intern/cycles/integrator/pass_accessor.cpp
index 0be3cf6860b..05318b7545b 100644
--- a/intern/cycles/integrator/pass_accessor.cpp
+++ b/intern/cycles/integrator/pass_accessor.cpp
@@ -18,7 +18,11 @@ CCL_NAMESPACE_BEGIN
  */
 
 PassAccessor::PassAccessInfo::PassAccessInfo(const BufferPass &pass)
-    : type(pass.type), mode(pass.mode), include_albedo(pass.include_albedo), offset(pass.offset)
+    : type(pass.type),
+      mode(pass.mode),
+      include_albedo(pass.include_albedo),
+      is_lightgroup(!pass.lightgroup.empty()),
+      offset(pass.offset)
 {
 }
 
@@ -127,7 +131,8 @@ bool PassAccessor::get_render_tile_pixels(const RenderBuffers *render_buffers,
 
   const PassType type = pass_access_info_.type;
   const PassMode mode = pass_access_info_.mode;
-  const PassInfo pass_info = Pass::get_info(type, pass_access_info_.include_albedo);
+  const PassInfo pass_info = Pass::get_info(
+      type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
   int num_written_components = pass_info.num_components;
 
   if (pass_info.num_components == 1) {
@@ -215,8 +220,8 @@ void PassAccessor::init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
                                             const Destination &destination) const
 {
   const PassMode mode = pass_access_info_.mode;
-  const PassInfo &pass_info = Pass::get_info(pass_access_info_.type,
-                                             pass_access_info_.include_albedo);
+  const PassInfo &pass_info = Pass::get_info(
+      pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
 
   kfilm_convert->pass_offset = pass_access_info_.offset;
   kfilm_convert->pass_stride = buffer_params.pass_stride;
@@ -279,8 +284,8 @@ bool PassAccessor::set_render_tile_pixels(RenderBuffers *render_buffers, const S
     return false;
   }
 
-  const PassInfo pass_info = Pass::get_info(pass_access_info_.type,
-                                            pass_access_info_.include_albedo);
+  const PassInfo pass_info = Pass::get_info(
+      pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
 
   const BufferParams &buffer_params = render_buffers->params;
 
diff --git a/intern/cycles/integrator/pass_accessor.h b/intern/cycles/integrator/pass_accessor.h
index 7de1d03961b..683d3a35272 100644
--- a/intern/cycles/integrator/pass_accessor.h
+++ b/intern/cycles/integrator/pass_accessor.h
@@ -28,6 +28,7 @@ class PassAccessor {
     PassType type = PASS_NONE;
     PassMode mode = PassMode::NOISY;
     bool include_albedo = false;
+    bool is_lightgroup = false;
     int offset = -1;
 
     /* For the shadow catcher matte pass: whether to approximate shadow catcher pass into its
diff --git a/intern/cycles/kernel/film/accumulate.h b/intern/cycles/kernel/film/accumulate.h
index d6a385a4bff..4c4165f3640 100644
--- a/intern/cycles/kernel/film/accumulate.h
+++ b/intern/cycles/kernel/film/accumulate.h
@@ -320,12 +320,13 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg,
 }
 
 /* Write background or emission to appropriate pass. */
-ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg,
-                                                                ConstIntegratorState state,
-                                                                float3 contribution,
-                                                                ccl_global float *ccl_restrict
-                                                                    buffer,
-                                                                const int pass)
+ccl_device_inline void kernel_accum_emission_or_background_pass(
+    KernelGlobals kg,
+    ConstIntegratorState state,
+    float3 contribution,
+    ccl_global float *ccl_restrict buffer,
+    const int pass,
+    const int lightgroup = LIGHTGROUP_NONE)
 {
   if (!(kernel_data.film.light_pass_flag & PASS_ANY)) {
     return;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list