Skip to content

Commit 2842ded

Browse files
tychedeliaAdriigbs
andauthored
Make shadows respect render layers (#20327)
Adopted from and closes #18747. Original work by @Adriigbs. Shadows and render layers are a bit complicated. Ideally, this filtering would be done at a higher level, but the camera entity just holds a list of references to the light entities for that view. Those light entities then compute what entities are visible from their perspective. We don't actually get a chance to filter camera and light visible entity until we queue the shadow pass, which is where this PR chooses to filter out entities that aren't visible in a camera from casting shadows. The alternative would be to store a per camera per light list of entities, which would greatly increase the amount of memory required for visible entities in multi-camera setups. --------- Signed-off-by: Adrian Graur <adrian.graur@tecnico.ulisboa.pt> Co-authored-by: Adrian Graur <adrian.graur@tecnico.ulisboa.pt> Co-authored-by: Adrian Graur <adri.graur16@gmail.com>
1 parent aa8a777 commit 2842ded

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

crates/bevy_pbr/src/render/light.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,7 +1865,7 @@ pub fn queue_shadows(
18651865
mut shadow_render_phases: ResMut<ViewBinnedRenderPhases<Shadow>>,
18661866
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
18671867
mesh_allocator: Res<MeshAllocator>,
1868-
view_lights: Query<(Entity, &ViewLightEntities), With<ExtractedView>>,
1868+
view_lights: Query<(Entity, &ViewLightEntities, Option<&RenderLayers>), With<ExtractedView>>,
18691869
view_light_entities: Query<(&LightEntity, &ExtractedView)>,
18701870
point_light_entities: Query<&RenderCubemapVisibleEntities, With<ExtractedPointLight>>,
18711871
directional_light_entities: Query<
@@ -1875,7 +1875,7 @@ pub fn queue_shadows(
18751875
spot_light_entities: Query<&RenderVisibleMeshEntities, With<ExtractedPointLight>>,
18761876
specialized_material_pipeline_cache: Res<SpecializedShadowMaterialPipelineCache>,
18771877
) {
1878-
for (entity, view_lights) in &view_lights {
1878+
for (entity, view_lights, camera_layers) in &view_lights {
18791879
for view_light_entity in view_lights.lights.iter().copied() {
18801880
let Ok((light_entity, extracted_view_light)) =
18811881
view_light_entities.get(view_light_entity)
@@ -1925,11 +1925,6 @@ pub fn queue_shadows(
19251925
continue;
19261926
};
19271927

1928-
// Skip the entity if it's cached in a bin and up to date.
1929-
if shadow_phase.validate_cached_entity(main_entity, *current_change_tick) {
1930-
continue;
1931-
}
1932-
19331928
let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(main_entity)
19341929
else {
19351930
continue;
@@ -1941,6 +1936,23 @@ pub fn queue_shadows(
19411936
continue;
19421937
}
19431938

1939+
let mesh_layers = mesh_instance
1940+
.shared
1941+
.render_layers
1942+
.as_ref()
1943+
.unwrap_or_default();
1944+
1945+
let camera_layers = camera_layers.unwrap_or_default();
1946+
1947+
if !camera_layers.intersects(mesh_layers) {
1948+
continue;
1949+
}
1950+
1951+
// Skip the entity if it's cached in a bin and up to date.
1952+
if shadow_phase.validate_cached_entity(main_entity, *current_change_tick) {
1953+
continue;
1954+
}
1955+
19441956
let Some(material_instance) = render_material_instances.instances.get(&main_entity)
19451957
else {
19461958
continue;

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ use bevy_render::camera::TemporalJitter;
7676
use bevy_render::prelude::Msaa;
7777
use bevy_render::sync_world::{MainEntity, MainEntityHashMap};
7878
use bevy_render::view::ExtractedView;
79+
use bevy_render::view::RenderLayers;
7980
use bevy_render::RenderSystems::PrepareAssets;
81+
8082
use bytemuck::{Pod, Zeroable};
8183
use nonmax::{NonMaxU16, NonMaxU32};
8284
use smallvec::{smallvec, SmallVec};
@@ -720,6 +722,8 @@ pub struct RenderMeshInstanceShared {
720722
pub lightmap_slab_index: Option<LightmapSlabIndex>,
721723
/// User supplied tag to identify this mesh instance.
722724
pub tag: u32,
725+
/// Render layers that this mesh instance belongs to.
726+
pub render_layers: Option<RenderLayers>,
723727
}
724728

725729
/// Information that is gathered during the parallel portion of mesh extraction
@@ -811,6 +815,7 @@ impl RenderMeshInstanceShared {
811815
tag: Option<&MeshTag>,
812816
not_shadow_caster: bool,
813817
no_automatic_batching: bool,
818+
render_layers: Option<&RenderLayers>,
814819
) -> Self {
815820
Self::for_cpu_building(
816821
previous_transform,
@@ -819,6 +824,7 @@ impl RenderMeshInstanceShared {
819824
default(),
820825
not_shadow_caster,
821826
no_automatic_batching,
827+
render_layers,
822828
)
823829
}
824830

@@ -830,6 +836,7 @@ impl RenderMeshInstanceShared {
830836
material_bindings_index: MaterialBindingId,
831837
not_shadow_caster: bool,
832838
no_automatic_batching: bool,
839+
render_layers: Option<&RenderLayers>,
833840
) -> Self {
834841
let mut mesh_instance_flags = RenderMeshInstanceFlags::empty();
835842
mesh_instance_flags.set(RenderMeshInstanceFlags::SHADOW_CASTER, !not_shadow_caster);
@@ -848,6 +855,7 @@ impl RenderMeshInstanceShared {
848855
material_bindings_index,
849856
lightmap_slab_index: None,
850857
tag: tag.map_or(0, |i| **i),
858+
render_layers: render_layers.cloned(),
851859
}
852860
}
853861

@@ -1313,6 +1321,7 @@ pub fn extract_meshes_for_cpu_building(
13131321
Has<NotShadowCaster>,
13141322
Has<NoAutomaticBatching>,
13151323
Has<VisibilityRange>,
1324+
Option<&RenderLayers>,
13161325
)>,
13171326
>,
13181327
) {
@@ -1332,6 +1341,7 @@ pub fn extract_meshes_for_cpu_building(
13321341
not_shadow_caster,
13331342
no_automatic_batching,
13341343
visibility_range,
1344+
render_layers,
13351345
)| {
13361346
if !view_visibility.get() {
13371347
return;
@@ -1364,6 +1374,7 @@ pub fn extract_meshes_for_cpu_building(
13641374
material_bindings_index,
13651375
not_shadow_caster,
13661376
no_automatic_batching,
1377+
render_layers,
13671378
);
13681379

13691380
let world_from_local = transform.affine();
@@ -1417,6 +1428,7 @@ type GpuMeshExtractionQuery = (
14171428
Has<NotShadowCaster>,
14181429
Has<NoAutomaticBatching>,
14191430
Has<VisibilityRange>,
1431+
Option<Read<RenderLayers>>,
14201432
);
14211433

14221434
/// Extracts meshes from the main world into the render world and queues
@@ -1536,6 +1548,7 @@ fn extract_mesh_for_gpu_building(
15361548
not_shadow_caster,
15371549
no_automatic_batching,
15381550
visibility_range,
1551+
render_layers,
15391552
): <GpuMeshExtractionQuery as QueryData>::Item<'_, '_>,
15401553
render_visibility_ranges: &RenderVisibilityRanges,
15411554
render_mesh_instances: &RenderMeshInstancesGpu,
@@ -1566,6 +1579,7 @@ fn extract_mesh_for_gpu_building(
15661579
tag,
15671580
not_shadow_caster,
15681581
no_automatic_batching,
1582+
render_layers,
15691583
);
15701584

15711585
let lightmap_uv_rect = pack_lightmap_uv_rect(lightmap.map(|lightmap| lightmap.uv_rect));

0 commit comments

Comments
 (0)