diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index c54210e84bb75..3012ced10d4f7 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -30,7 +30,10 @@ pub mod contact_shadows; #[cfg(feature = "bevy_gltf")] mod gltf; use bevy_light::cluster::GlobalClusterSettings; -use bevy_render::sync_component::SyncComponent; +use bevy_render::{ + sync_component::SyncComponent, + view::{RenderExtractedShadowMapVisibleEntities, RenderShadowMapVisibleEntities}, +}; pub use contact_shadows::{ ContactShadows, ContactShadowsBuffer, ContactShadowsPlugin, ContactShadowsUniform, ViewContactShadowsUniformOffset, @@ -418,7 +421,9 @@ impl Plugin for PbrPlugin { render_app .world_mut() .add_observer(remove_light_view_entities); - render_app.world_mut().add_observer(extracted_light_removed); + render_app + .world_mut() + .add_observer(remove_point_and_spot_light_view_entities); render_app.add_systems( Core3d, @@ -477,16 +482,34 @@ pub fn stbn_placeholder() -> Image { } impl SyncComponent for DirectionalLight { - type Target = Self; + type Target = ( + Self, + ExtractedDirectionalLight, + RenderExtractedShadowMapVisibleEntities, + RenderShadowMapVisibleEntities, + DirectionalLightViewEntities, + ); } impl SyncComponent for PointLight { - type Target = Self; + type Target = ( + Self, + ExtractedPointLight, + RenderExtractedShadowMapVisibleEntities, + RenderShadowMapVisibleEntities, + PointAndSpotLightViewEntities, + ); } impl SyncComponent for SpotLight { - type Target = Self; + type Target = ( + Self, + ExtractedPointLight, + RenderExtractedShadowMapVisibleEntities, + RenderShadowMapVisibleEntities, + PointAndSpotLightViewEntities, + ); } impl SyncComponent for RectLight { - type Target = Self; + type Target = (Self, ExtractedRectLight); } impl SyncComponent for AmbientLight { type Target = Self; diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 5bcba533ef152..d55ef9443d595 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -45,8 +45,7 @@ use bevy_render::mesh::allocator::MeshSlabs; use bevy_render::occlusion_culling::{ OcclusionCulling, OcclusionCullingSubview, OcclusionCullingSubviewEntities, }; -use bevy_render::sync_world::{MainEntity, RenderEntity}; -use bevy_render::sync_world::{MainEntityHashMap, MainEntityHashSet}; +use bevy_render::sync_world::{MainEntity, MainEntityHashMap, RenderEntity}; use bevy_render::view::{ RenderExtractedShadowMapVisibleEntities, RenderShadowMapVisibleEntities, RenderVisibleEntities, VisibilityExtractionSystemParam, @@ -421,17 +420,6 @@ pub fn extract_lights( &mut RenderExtractedShadowMapVisibleEntities, &mut RenderShadowMapVisibleEntities, )>, - ( - mut removed_point_lights, - mut removed_spot_lights, - mut removed_directional_lights, - mut removed_rect_lights, - ): ( - Extract>, - Extract>, - Extract>, - Extract>, - ), ) { let mapper = &visibility_extraction_system_param.mapper; @@ -453,14 +441,6 @@ pub fn extract_lights( // https://catlikecoding.com/unity/tutorials/custom-srp/point-and-spot-shadows/ let point_light_texel_size = 2.0 / point_light_shadow_map.size as f32; - // Keep track of all entities of a type that we updated this frame, so that - // we don't incorrectly remove the components later even if they show up in - // `RemovedComponents`. - let mut seen_point_light_main_entities = MainEntityHashSet::default(); - let mut seen_spot_light_main_entities = MainEntityHashSet::default(); - let mut seen_directional_light_main_entities = MainEntityHashSet::default(); - let mut seen_rect_light_main_entities = MainEntityHashSet::default(); - for ( main_entity, render_entity, @@ -472,8 +452,6 @@ pub fn extract_lights( volumetric_light, ) in point_lights.iter() { - seen_point_light_main_entities.insert(main_entity.into()); - if !view_visibility.get() { if let Ok(mut entity_commands) = commands.get_entity(render_entity) { entity_commands.remove::(); @@ -586,8 +564,6 @@ pub fn extract_lights( volumetric_light, ) in spot_lights.iter() { - seen_spot_light_main_entities.insert(main_entity.into()); - if !view_visibility.get() { if let Ok(mut entity_commands) = commands.get_entity(render_entity) { entity_commands.remove::(); @@ -706,8 +682,6 @@ pub fn extract_lights( sun_disk, ) in &directional_lights { - seen_directional_light_main_entities.insert(main_entity.into()); - if !view_visibility.get() { commands .get_entity(entity) @@ -850,8 +824,6 @@ pub fn extract_lights( } for (main_entity, render_entity, rect_light, transform, view_visibility) in &rect_lights { - seen_rect_light_main_entities.insert(main_entity.into()); - if !view_visibility.get() { if let Ok(mut entity_commands) = commands.get_entity(render_entity) { entity_commands.remove::(); @@ -879,64 +851,6 @@ pub fn extract_lights( )); } - // Remove extracted light components from entities that have had their - // light components removed. - remove_components::( - &mut commands, - mapper, - &mut removed_point_lights, - &seen_point_light_main_entities, - ); - remove_components::( - &mut commands, - mapper, - &mut removed_spot_lights, - &seen_spot_light_main_entities, - ); - remove_components::( - &mut commands, - mapper, - &mut removed_directional_lights, - &seen_directional_light_main_entities, - ); - remove_components::( - &mut commands, - mapper, - &mut removed_rect_lights, - &seen_rect_light_main_entities, - ); - - // A helper function that removes a render-world component `RWC` when a - // main-world component `MC` is removed. - // - // `seen_entities` is the list of all entities with that component that were - // updated this frame. It's needed because presence in the - // `RemovedComponents` table for the main-world component isn't enough to - // determine whether the render-world component can be removed, as the - // main-world component might have been removed and then re-added in the - // same frame. - fn remove_components( - commands: &mut Commands, - mapper: &Query<&RenderEntity>, - removed_components: &mut RemovedComponents, - seen_entities: &MainEntityHashSet, - ) where - MC: Component, - RWC: Component, - { - // As usual, only remove components if we didn't process them in the - // outer extraction function, because of the possibility that the - // component might have been removed and re-added in the same frame. - for main_entity in removed_components.read() { - if !seen_entities.contains(&MainEntity::from(main_entity)) - && let Ok(render_entity) = mapper.get(main_entity) - && let Ok(mut entity_commands) = commands.get_entity(**render_entity) - { - entity_commands.remove::(); - } - } - } - /// Clears out any shadow maps that may be present for a light with shadow /// mapping turned off. fn clear_shadow_maps(commands: &mut Commands, render_entity: Entity) { @@ -965,17 +879,6 @@ pub(crate) fn add_light_view_entities( } } -/// Removes [`DirectionalLightViewEntities`] when light is removed. See -/// [`add_light_view_entities`]. -pub(crate) fn extracted_light_removed( - remove: On, - mut commands: Commands, -) { - if let Ok(mut v) = commands.get_entity(remove.entity) { - v.try_remove::(); - } -} - pub(crate) fn remove_light_view_entities( remove: On, query: Query<&DirectionalLightViewEntities>, @@ -992,6 +895,20 @@ pub(crate) fn remove_light_view_entities( } } +pub(crate) fn remove_point_and_spot_light_view_entities( + remove: On, + query: Query<&PointAndSpotLightViewEntities>, + mut commands: Commands, +) { + if let Ok(entities) = query.get(remove.entity) { + for e in entities.0.iter().copied() { + if let Ok(mut v) = commands.get_entity(e) { + v.despawn(); + } + } + } +} + /// A component that stores the shadow maps associated with a point or spot /// light. ///