Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -477,16 +482,34 @@ pub fn stbn_placeholder() -> Image {
}

impl SyncComponent<PbrPlugin> for DirectionalLight {
type Target = Self;
type Target = (
Self,
ExtractedDirectionalLight,
RenderExtractedShadowMapVisibleEntities,
RenderShadowMapVisibleEntities,
DirectionalLightViewEntities,
);
}
impl SyncComponent<PbrPlugin> for PointLight {
type Target = Self;
type Target = (
Self,
ExtractedPointLight,
RenderExtractedShadowMapVisibleEntities,
RenderShadowMapVisibleEntities,
PointAndSpotLightViewEntities,
);
}
impl SyncComponent<PbrPlugin> for SpotLight {
type Target = Self;
type Target = (
Self,
ExtractedPointLight,
RenderExtractedShadowMapVisibleEntities,
RenderShadowMapVisibleEntities,
PointAndSpotLightViewEntities,
);
}
impl SyncComponent<PbrPlugin> for RectLight {
type Target = Self;
type Target = (Self, ExtractedRectLight);
}
impl SyncComponent<PbrPlugin> for AmbientLight {
type Target = Self;
Expand Down
113 changes: 15 additions & 98 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<RemovedComponents<PointLight>>,
Extract<RemovedComponents<SpotLight>>,
Extract<RemovedComponents<DirectionalLight>>,
Extract<RemovedComponents<RectLight>>,
),
) {
let mapper = &visibility_extraction_system_param.mapper;

Expand All @@ -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,
Expand All @@ -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::<ExtractedPointLight>();
Expand Down Expand Up @@ -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::<ExtractedPointLight>();
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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::<ExtractedRectLight>();
Expand Down Expand Up @@ -879,64 +851,6 @@ pub fn extract_lights(
));
}

// Remove extracted light components from entities that have had their
// light components removed.
remove_components::<PointLight, ExtractedPointLight>(
&mut commands,
mapper,
&mut removed_point_lights,
&seen_point_light_main_entities,
);
remove_components::<SpotLight, ExtractedPointLight>(
&mut commands,
mapper,
&mut removed_spot_lights,
&seen_spot_light_main_entities,
);
remove_components::<DirectionalLight, ExtractedDirectionalLight>(
&mut commands,
mapper,
&mut removed_directional_lights,
&seen_directional_light_main_entities,
);
remove_components::<RectLight, ExtractedRectLight>(
&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<MC, RWC>(
commands: &mut Commands,
mapper: &Query<&RenderEntity>,
removed_components: &mut RemovedComponents<MC>,
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::<RWC>();
}
}
}

/// 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) {
Expand Down Expand Up @@ -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<Remove, ExtractedDirectionalLight>,
mut commands: Commands,
) {
if let Ok(mut v) = commands.get_entity(remove.entity) {
v.try_remove::<DirectionalLightViewEntities>();
}
}

pub(crate) fn remove_light_view_entities(
remove: On<Remove, DirectionalLightViewEntities>,
query: Query<&DirectionalLightViewEntities>,
Expand All @@ -992,6 +895,20 @@ pub(crate) fn remove_light_view_entities(
}
}

pub(crate) fn remove_point_and_spot_light_view_entities(
remove: On<Remove, PointAndSpotLightViewEntities>,
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.
///
Expand Down