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] - increase the maximum number of point lights with shadows to the max supported by the device #4435

Closed
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
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ fn cluster_space_light_aabb(
}

// 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 limit the number of point light shadows to render based on the device and
// we keep a stable set of lights visible
pub(crate) fn point_light_order(
(entity_1, shadows_enabled_1): (&Entity, &bool),
Expand Down
24 changes: 13 additions & 11 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,7 @@ pub struct GpuLights {

// NOTE: this must be kept in sync with the same constants in pbr.frag
pub const MAX_UNIFORM_BUFFER_POINT_LIGHTS: usize = 256;
// FIXME: How should we handle shadows for clustered forward? Limiting to maximum 10
// point light shadow maps for now
#[cfg(feature = "webgl")]
pub const MAX_POINT_LIGHT_SHADOW_MAPS: usize = 1;
#[cfg(not(feature = "webgl"))]
pub const MAX_POINT_LIGHT_SHADOW_MAPS: usize = 10;
pub const MAX_DIRECTIONAL_LIGHTS: usize = 1;
pub const POINT_SHADOW_LAYERS: u32 = (6 * MAX_POINT_LIGHT_SHADOW_MAPS) as u32;
pub const DIRECTIONAL_SHADOW_LAYERS: u32 = MAX_DIRECTIONAL_LIGHTS as u32;
pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float;

Expand Down Expand Up @@ -704,8 +697,17 @@ pub fn prepare_lights(

let mut point_lights: Vec<_> = point_lights.iter().collect::<Vec<_>>();

#[cfg(not(feature = "webgl"))]
let max_point_light_shadow_maps = point_lights
.iter()
.filter(|light| light.1.shadows_enabled)
.count()
.min((render_device.limits().max_texture_array_layers / 6) as usize);
Copy link
Contributor

@IceSentry IceSentry Apr 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the 6 here and on line 662? I'm not sure what it's supposed to mean

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. It is a ‘magic number’ I guess though it’s already been used elsewhere so I’d fix it in a separate PR. Point lights use cubemaps for shadow mapping. Cubemaps are array textures with 6 layers per cubemap, one for each cube face. That’s where the 6 comes from.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, doesn't need to be fixed here, it was just for my own learning purposes, thanks!

#[cfg(feature = "webgl")]
mockersf marked this conversation as resolved.
Show resolved Hide resolved
let max_point_light_shadow_maps = 1;

// 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.
// to render at most `max_point_light_shadow_maps` point light shadows.
point_lights.sort_by(|(entity_1, light_1), (entity_2, light_2)| {
point_light_order(
(entity_1, &light_1.shadows_enabled),
Expand All @@ -723,7 +725,7 @@ pub fn prepare_lights(
for (index, &(entity, light)) in point_lights.iter().enumerate() {
let mut flags = PointLightFlags::NONE;
// Lights are sorted, shadow enabled lights are first
if light.shadows_enabled && index < MAX_POINT_LIGHT_SHADOW_MAPS {
if light.shadows_enabled && index < max_point_light_shadow_maps {
flags |= PointLightFlags::SHADOWS_ENABLED;
}
gpu_point_lights.push(GpuPointLight {
Expand Down Expand Up @@ -759,7 +761,7 @@ pub fn prepare_lights(
size: Extent3d {
width: point_light_shadow_map.size as u32,
height: point_light_shadow_map.size as u32,
depth_or_array_layers: POINT_SHADOW_LAYERS,
depth_or_array_layers: max_point_light_shadow_maps.max(1) as u32 * 6,
},
mip_level_count: 1,
sample_count: 1,
Expand Down Expand Up @@ -816,7 +818,7 @@ pub fn prepare_lights(
for &(light_entity, light) in point_lights
.iter()
// Lights are sorted, shadow enabled lights are first
.take(MAX_POINT_LIGHT_SHADOW_MAPS)
.take(max_point_light_shadow_maps)
.filter(|(_, light)| light.shadows_enabled)
{
let light_index = *global_light_meta
Expand Down