add Visibility for lights (#3958)

# Objective

Add Visibility for lights

## Solution

- add Visibility to PointLightBundle and DirectionLightBundle
- filter lights used by Visibility.is_visible

note: includes changes from #3916 due to overlap, will be cleaner after that is merged
This commit is contained in:
robtfm 2022-03-05 03:23:01 +00:00
parent 72bb38cad5
commit 575ea81d7b
3 changed files with 37 additions and 15 deletions

View file

@ -71,6 +71,8 @@ pub struct PointLightBundle {
pub cubemap_frusta: CubemapFrusta, pub cubemap_frusta: CubemapFrusta,
pub transform: Transform, pub transform: Transform,
pub global_transform: GlobalTransform, pub global_transform: GlobalTransform,
/// Enables or disables the light
pub visibility: Visibility,
} }
/// A component bundle for [`DirectionalLight`] entities. /// A component bundle for [`DirectionalLight`] entities.
@ -81,4 +83,6 @@ pub struct DirectionalLightBundle {
pub visible_entities: VisibleEntities, pub visible_entities: VisibleEntities,
pub transform: Transform, pub transform: Transform,
pub global_transform: GlobalTransform, pub global_transform: GlobalTransform,
/// Enables or disables the light
pub visibility: Visibility,
} }

View file

@ -480,7 +480,7 @@ fn ndc_position_to_cluster(
} }
// Sort point lights with shadows enabled first, then by a stable key so that the index // Sort point lights with shadows enabled first, then by a stable key so that the index
// can be used to render at most `MAX_POINT_LIGHT_SHADOW_MAPS` point light shadows, and // can be used to render at most `MAX_POINT_LIGHT_SHADOW_MAPS` point light shadows and
// we keep a stable set of lights visible // we keep a stable set of lights visible
pub(crate) fn point_light_order( pub(crate) fn point_light_order(
(entity_1, shadows_enabled_1): (&Entity, &bool), (entity_1, shadows_enabled_1): (&Entity, &bool),
@ -506,7 +506,7 @@ pub(crate) fn assign_lights_to_clusters(
mut commands: Commands, mut commands: Commands,
mut global_lights: ResMut<VisiblePointLights>, mut global_lights: ResMut<VisiblePointLights>,
mut views: Query<(Entity, &GlobalTransform, &Camera, &Frustum, &mut Clusters)>, mut views: Query<(Entity, &GlobalTransform, &Camera, &Frustum, &mut Clusters)>,
lights_query: Query<(Entity, &GlobalTransform, &PointLight)>, lights_query: Query<(Entity, &GlobalTransform, &PointLight, &Visibility)>,
mut lights: Local<Vec<PointLightAssignmentData>>, mut lights: Local<Vec<PointLightAssignmentData>>,
mut max_point_lights_warning_emitted: Local<bool>, mut max_point_lights_warning_emitted: Local<bool>,
) { ) {
@ -514,12 +514,15 @@ pub(crate) fn assign_lights_to_clusters(
lights.extend( lights.extend(
lights_query lights_query
.iter() .iter()
.map(|(entity, transform, light)| PointLightAssignmentData { .filter(|(.., visibility)| visibility.is_visible)
entity, .map(
translation: transform.translation, |(entity, transform, light, _visibility)| PointLightAssignmentData {
shadows_enabled: light.shadows_enabled, entity,
range: light.range, translation: transform.translation,
}), shadows_enabled: light.shadows_enabled,
range: light.range,
},
),
); );
if lights.len() > MAX_POINT_LIGHTS { if lights.len() > MAX_POINT_LIGHTS {
@ -699,13 +702,18 @@ pub(crate) fn assign_lights_to_clusters(
} }
pub fn update_directional_light_frusta( pub fn update_directional_light_frusta(
mut views: Query<(&GlobalTransform, &DirectionalLight, &mut Frustum)>, mut views: Query<(
&GlobalTransform,
&DirectionalLight,
&mut Frustum,
&Visibility,
)>,
) { ) {
for (transform, directional_light, mut frustum) in views.iter_mut() { for (transform, directional_light, mut frustum, visibility) in views.iter_mut() {
// The frustum is used for culling meshes to the light for shadow mapping // The frustum is used for culling meshes to the light for shadow mapping
// so if shadow mapping is disabled for this light, then the frustum is // so if shadow mapping is disabled for this light, then the frustum is
// not needed. // not needed.
if !directional_light.shadows_enabled { if !directional_light.shadows_enabled || !visibility.is_visible {
continue; continue;
} }
@ -781,6 +789,7 @@ pub fn check_light_mesh_visibility(
&Frustum, &Frustum,
&mut VisibleEntities, &mut VisibleEntities,
Option<&RenderLayers>, Option<&RenderLayers>,
&Visibility,
)>, )>,
mut visible_entity_query: Query< mut visible_entity_query: Query<
( (
@ -795,13 +804,13 @@ pub fn check_light_mesh_visibility(
>, >,
) { ) {
// Directonal lights // Directonal lights
for (directional_light, frustum, mut visible_entities, maybe_view_mask) in for (directional_light, frustum, mut visible_entities, maybe_view_mask, visibility) in
directional_lights.iter_mut() directional_lights.iter_mut()
{ {
visible_entities.entities.clear(); visible_entities.entities.clear();
// NOTE: If shadow mapping is disabled for the light then it must have no visible entities // NOTE: If shadow mapping is disabled for the light then it must have no visible entities
if !directional_light.shadows_enabled { if !directional_light.shadows_enabled || !visibility.is_visible {
continue; continue;
} }

View file

@ -25,7 +25,9 @@ use bevy_render::{
render_resource::{std140::AsStd140, *}, render_resource::{std140::AsStd140, *},
renderer::{RenderContext, RenderDevice, RenderQueue}, renderer::{RenderContext, RenderDevice, RenderQueue},
texture::*, texture::*,
view::{ExtractedView, ViewUniform, ViewUniformOffset, ViewUniforms, VisibleEntities}, view::{
ExtractedView, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility, VisibleEntities,
},
}; };
use bevy_transform::components::GlobalTransform; use bevy_transform::components::GlobalTransform;
use bevy_utils::{ use bevy_utils::{
@ -337,6 +339,7 @@ pub fn extract_lights(
&DirectionalLight, &DirectionalLight,
&mut VisibleEntities, &mut VisibleEntities,
&GlobalTransform, &GlobalTransform,
&Visibility,
)>, )>,
) { ) {
commands.insert_resource(ExtractedAmbientLight { commands.insert_resource(ExtractedAmbientLight {
@ -383,7 +386,13 @@ pub fn extract_lights(
} }
} }
for (entity, directional_light, visible_entities, transform) in directional_lights.iter_mut() { for (entity, directional_light, visible_entities, transform, visibility) in
directional_lights.iter_mut()
{
if !visibility.is_visible {
continue;
}
// Calulate the directional light shadow map texel size using the largest x,y dimension of // Calulate the directional light shadow map texel size using the largest x,y dimension of
// the orthographic projection divided by the shadow map resolution // the orthographic projection divided by the shadow map resolution
// NOTE: When using various PCF kernel sizes, this will need to be adjusted, according to: // NOTE: When using various PCF kernel sizes, this will need to be adjusted, according to: