From e16b6ac3da89ef428d0b733d1375ba27cf2f59be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 12 Jun 2025 14:18:29 +0200 Subject: [PATCH] EEVEE: Add support for view layer overrides This was a missing features in EEVEE for ages which was in fact very easy to implement. EEVEE implements the sample override like the default `Use` value in Cycles. It always override the sample count if not 0. Adding a new option for changing this behavior just like Cycles can be done later while at the same time making the option more understandable and its value moved to the blender's DNA. This PR moves the UI panel to the Blender side to be shared between Cycles and EEVEE. Pull Request: https://projects.blender.org/blender/blender/pulls/140219 --- intern/cycles/blender/addon/ui.py | 18 ---------------- .../startup/bl_ui/properties_view_layer.py | 21 +++++++++++++++++++ .../draw/engines/eevee/eevee_material.cc | 7 +++++-- .../draw/engines/eevee/eevee_material.hh | 2 ++ .../draw/engines/eevee/eevee_sampling.cc | 7 ++++++- .../blender/draw/engines/eevee/eevee_world.cc | 5 +++++ 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 1544a88b859..d7399e87886 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -978,23 +978,6 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel): sub.active = scene.cycles.use_denoising -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, "world_override") - layout.prop(view_layer, "samples") - - class CYCLES_RENDER_PT_passes(CyclesButtonsPanel, Panel): bl_label = "Passes" bl_context = "view_layer" @@ -2566,7 +2549,6 @@ classes = ( CYCLES_RENDER_PT_passes_aov, CYCLES_RENDER_PT_passes_lightgroups, CYCLES_RENDER_PT_filter, - CYCLES_RENDER_PT_override, CYCLES_PT_post_processing, CYCLES_CAMERA_PT_dof, CYCLES_CAMERA_PT_dof_aperture, diff --git a/scripts/startup/bl_ui/properties_view_layer.py b/scripts/startup/bl_ui/properties_view_layer.py index 3bca2185084..60776831c4e 100644 --- a/scripts/startup/bl_ui/properties_view_layer.py +++ b/scripts/startup/bl_ui/properties_view_layer.py @@ -271,6 +271,26 @@ class VIEWLAYER_PT_filter(ViewLayerButtonsPanel, Panel): sub.active = scene.render.use_motion_blur +class VIEWLAYER_PT_override(ViewLayerButtonsPanel, Panel): + bl_label = "Override" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = { + 'BLENDER_EEVEE_NEXT', + 'CYCLES', + } + + 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, "world_override") + layout.prop(view_layer, "samples") + + class VIEWLAYER_PT_layer_custom_props(PropertyPanel, Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -290,6 +310,7 @@ classes = ( VIEWLAYER_PT_layer_passes_aov, VIEWLAYER_PT_layer_passes_lightgroups, VIEWLAYER_PT_filter, + VIEWLAYER_PT_override, VIEWLAYER_PT_layer_custom_props, VIEWLAYER_UL_aov, ) diff --git a/source/blender/draw/engines/eevee/eevee_material.cc b/source/blender/draw/engines/eevee/eevee_material.cc index f3695243596..22f153b9a53 100644 --- a/source/blender/draw/engines/eevee/eevee_material.cc +++ b/source/blender/draw/engines/eevee/eevee_material.cc @@ -164,6 +164,8 @@ void MaterialModule::begin_sync() queued_textures_count = 0; queued_optimize_shaders_count = 0; + material_override = DEG_get_evaluated(inst_.depsgraph, inst_.view_layer->mat_override); + uint64_t next_update = GPU_pass_global_compilation_count(); gpu_pass_last_update_ = gpu_pass_next_update_; gpu_pass_next_update_ = next_update; @@ -530,7 +532,7 @@ MaterialArray &MaterialModule::material_array_get(Object *ob, bool has_motion) const int materials_len = BKE_object_material_used_with_fallback_eval(*ob); for (auto i : IndexRange(materials_len)) { - ::Material *blender_mat = material_from_slot(ob, i); + ::Material *blender_mat = (material_override) ? material_override : material_from_slot(ob, i); Material &mat = material_sync(ob, blender_mat, to_material_geometry(ob), has_motion); /* \note Perform a whole copy since next material_sync() can move the Material memory location * (i.e: because of its container growing) */ @@ -545,7 +547,8 @@ Material &MaterialModule::material_get(Object *ob, int mat_nr, eMaterialGeometry geometry_type) { - ::Material *blender_mat = material_from_slot(ob, mat_nr); + ::Material *blender_mat = (material_override) ? material_override : + material_from_slot(ob, mat_nr); Material &mat = material_sync(ob, blender_mat, geometry_type, has_motion); return mat; } diff --git a/source/blender/draw/engines/eevee/eevee_material.hh b/source/blender/draw/engines/eevee/eevee_material.hh index 52f8a247f46..52ee158e053 100644 --- a/source/blender/draw/engines/eevee/eevee_material.hh +++ b/source/blender/draw/engines/eevee/eevee_material.hh @@ -355,6 +355,8 @@ class MaterialModule { ::Material *default_surface; ::Material *default_volume; + ::Material *material_override = nullptr; + int64_t queued_shaders_count = 0; int64_t queued_textures_count = 0; int64_t queued_optimize_shaders_count = 0; diff --git a/source/blender/draw/engines/eevee/eevee_sampling.cc b/source/blender/draw/engines/eevee/eevee_sampling.cc index 9bd1091be90..6d16828aee3 100644 --- a/source/blender/draw/engines/eevee/eevee_sampling.cc +++ b/source/blender/draw/engines/eevee/eevee_sampling.cc @@ -27,7 +27,12 @@ namespace blender::eevee { void Sampling::init(const Scene *scene) { - sample_count_ = inst_.is_viewport() ? scene->eevee.taa_samples : scene->eevee.taa_render_samples; + /* Note: Cycles have different option for view layers sample overrides. The current behavior + * matches the default `Use`, which simply override if non-zero. */ + uint64_t render_sample_count = (inst_.view_layer->samples > 0) ? inst_.view_layer->samples : + scene->eevee.taa_render_samples; + + sample_count_ = inst_.is_viewport() ? scene->eevee.taa_samples : render_sample_count; if (inst_.is_image_render) { sample_count_ = math::max(uint64_t(1), sample_count_); diff --git a/source/blender/draw/engines/eevee/eevee_world.cc b/source/blender/draw/engines/eevee/eevee_world.cc index 649323928ba..3b64de054df 100644 --- a/source/blender/draw/engines/eevee/eevee_world.cc +++ b/source/blender/draw/engines/eevee/eevee_world.cc @@ -126,6 +126,11 @@ void World::sync() bl_world = scene_world_get(); } + ::World *world_override = DEG_get_evaluated(inst_.depsgraph, inst_.view_layer->world_override); + if (world_override) { + bl_world = world_override; + } + bNodeTree *ntree = (bl_world->nodetree && bl_world->use_nodes) ? bl_world->nodetree : default_tree.nodetree_get(bl_world);