Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - add Visibility for lights #3958

Closed
wants to merge 24 commits into from
Closed
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
4 changes: 4 additions & 0 deletions crates/bevy_pbr/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub struct PointLightBundle {
pub cubemap_frusta: CubemapFrusta,
pub transform: Transform,
pub global_transform: GlobalTransform,
/// Enables or disables the light
pub visibility: Visibility,
robtfm marked this conversation as resolved.
Show resolved Hide resolved
}

/// A component bundle for [`DirectionalLight`] entities.
Expand All @@ -81,4 +83,6 @@ pub struct DirectionalLightBundle {
pub visible_entities: VisibleEntities,
pub transform: Transform,
pub global_transform: GlobalTransform,
/// Enables or disables the light
pub visibility: Visibility,
robtfm marked this conversation as resolved.
Show resolved Hide resolved
}
35 changes: 22 additions & 13 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
// 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
robtfm marked this conversation as resolved.
Show resolved Hide resolved
// we keep a stable set of lights visible
pub(crate) fn point_light_order(
(entity_1, shadows_enabled_1): (&Entity, &bool),
Expand All @@ -506,20 +506,23 @@ pub(crate) fn assign_lights_to_clusters(
mut commands: Commands,
mut global_lights: ResMut<VisiblePointLights>,
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 max_point_lights_warning_emitted: Local<bool>,
) {
// collect just the relevant light query data into a persisted vec to avoid reallocating each frame
lights.extend(
lights_query
.iter()
.map(|(entity, transform, light)| PointLightAssignmentData {
entity,
translation: transform.translation,
shadows_enabled: light.shadows_enabled,
range: light.range,
}),
.filter(|(.., visibility)| visibility.is_visible)
.map(
|(entity, transform, light, _visibility)| PointLightAssignmentData {
entity,
translation: transform.translation,
shadows_enabled: light.shadows_enabled,
range: light.range,
},
),
);

if lights.len() > MAX_POINT_LIGHTS {
Expand Down Expand Up @@ -699,13 +702,18 @@ pub(crate) fn assign_lights_to_clusters(
}

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
// so if shadow mapping is disabled for this light, then the frustum is
// not needed.
if !directional_light.shadows_enabled {
if !directional_light.shadows_enabled || !visibility.is_visible {
continue;
}

Expand Down Expand Up @@ -781,6 +789,7 @@ pub fn check_light_mesh_visibility(
&Frustum,
&mut VisibleEntities,
Option<&RenderLayers>,
&Visibility,
)>,
mut visible_entity_query: Query<
(
Expand All @@ -795,13 +804,13 @@ pub fn check_light_mesh_visibility(
>,
) {
// 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()
{
visible_entities.entities.clear();

// 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;
}

Expand Down
13 changes: 11 additions & 2 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ use bevy_render::{
render_resource::{std140::AsStd140, *},
renderer::{RenderContext, RenderDevice, RenderQueue},
texture::*,
view::{ExtractedView, ViewUniform, ViewUniformOffset, ViewUniforms, VisibleEntities},
view::{
ExtractedView, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility, VisibleEntities,
},
};
use bevy_transform::components::GlobalTransform;
use bevy_utils::{
Expand Down Expand Up @@ -337,6 +339,7 @@ pub fn extract_lights(
&DirectionalLight,
&mut VisibleEntities,
&GlobalTransform,
&Visibility,
)>,
) {
commands.insert_resource(ExtractedAmbientLight {
Expand Down Expand Up @@ -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
// the orthographic projection divided by the shadow map resolution
// NOTE: When using various PCF kernel sizes, this will need to be adjusted, according to:
Expand Down