From 96d8abc0cdd267df8bf44f57458442f2ebda007c Mon Sep 17 00:00:00 2001 From: Dusty DeWeese Date: Thu, 3 Mar 2022 23:21:06 -0800 Subject: [PATCH 1/3] Avoid windows with a physical size of zero --- crates/bevy_pbr/src/light.rs | 12 ++++++------ crates/bevy_render/src/camera/camera.rs | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index d05d5c44c5381..0e2e423fac8a5 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -723,11 +723,15 @@ pub(crate) fn assign_lights_to_clusters( } let clusters = clusters.into_inner(); - let screen_size = camera.target.get_physical_size(&windows, &images); + let screen_size = + if let Some(screen_size) = camera.target.get_physical_size(&windows, &images) { + screen_size + } else { + continue; + }; clusters.lights.clear(); - let screen_size = screen_size.unwrap_or_default(); let mut requested_cluster_dimensions = config.dimensions_for_screen_size(screen_size); let view_transform = camera_transform.compute_matrix(); @@ -857,10 +861,6 @@ pub(crate) fn assign_lights_to_clusters( VisiblePointLights::default, ); - if screen_size.x == 0 || screen_size.y == 0 { - continue; - } - // Calculate the x/y/z cluster frustum planes in view space let mut x_planes = Vec::with_capacity(clusters.dimensions.x as usize + 1); let mut y_planes = Vec::with_capacity(clusters.dimensions.y as usize + 1); diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index cdcd951c49c73..a69892cd22a3a 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -79,6 +79,7 @@ impl RenderTarget { UVec2::new(width, height) }), } + .filter(|size| size.x > 0 && size.y > 0) } pub fn get_logical_size(&self, windows: &Windows, images: &Assets) -> Option { match self { @@ -312,8 +313,8 @@ pub fn extract_cameras( ExtractedView { projection: camera.projection_matrix, transform: *transform, - width: size.x.max(1), - height: size.y.max(1), + width: size.x, + height: size.y, near: camera.near, far: camera.far, }, From e14043f6a322600503e2edd23af4441c4f395c1c Mon Sep 17 00:00:00 2001 From: Dusty DeWeese Date: Wed, 13 Apr 2022 10:52:07 -0700 Subject: [PATCH 2/3] improve Clusters clearing logic - clear clusters on ClusterConfig::None or missing render target - don't clear cluster.lights otherwise so it can be reused --- crates/bevy_pbr/src/light.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 0e2e423fac8a5..0ac0cb7cb2b23 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -389,6 +389,13 @@ impl Clusters { // NOTE: Maximum 4096 clusters due to uniform buffer size constraints debug_assert!(self.dimensions.x * self.dimensions.y * self.dimensions.z <= 4096); } + fn clear(&mut self) { + self.tile_size = UVec2::ONE; + self.dimensions = UVec3::ONE; + self.near = 0.0; + self.far = 0.0; + self.lights.clear(); + } } fn clip_to_view(inverse_projection: Mat4, clip: Vec4) -> Vec4 { @@ -717,21 +724,22 @@ pub(crate) fn assign_lights_to_clusters( for (view_entity, camera_transform, camera, frustum, config, clusters, mut visible_lights) in views.iter_mut() { + let clusters = clusters.into_inner(); + if matches!(config, ClusterConfig::None) && visible_lights.is_some() { commands.entity(view_entity).remove::(); + clusters.clear(); continue; } - let clusters = clusters.into_inner(); let screen_size = if let Some(screen_size) = camera.target.get_physical_size(&windows, &images) { screen_size } else { + clusters.clear(); continue; }; - clusters.lights.clear(); - let mut requested_cluster_dimensions = config.dimensions_for_screen_size(screen_size); let view_transform = camera_transform.compute_matrix(); From 60729c505b56f1cde13798a9500bc04337356008 Mon Sep 17 00:00:00 2001 From: Dusty DeWeese Date: Wed, 13 Apr 2022 10:53:46 -0700 Subject: [PATCH 3/3] avoid unnecessary allocation for visible_lights --- crates/bevy_pbr/src/light.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 0ac0cb7cb2b23..cac50be971c3a 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -926,16 +926,7 @@ pub(crate) fn assign_lights_to_clusters( z_planes.push(Plane::new(normal.extend(d))); } - let mut visible_lights_scratch = Vec::new(); - - { - // reuse existing visible lights Vec, if it exists - let visible_lights = if let Some(visible_lights) = visible_lights.as_mut() { - visible_lights.entities.clear(); - &mut visible_lights.entities - } else { - &mut visible_lights_scratch - }; + let mut update_from_light_intersections = |visible_lights: &mut Vec| { for light in lights.iter() { let light_sphere = Sphere { center: Vec3A::from(light.translation), @@ -1088,12 +1079,18 @@ pub(crate) fn assign_lights_to_clusters( } } } - } + }; - if visible_lights.is_none() { - commands.entity(view_entity).insert(VisiblePointLights { - entities: visible_lights_scratch, - }); + // reuse existing visible lights Vec, if it exists + if let Some(visible_lights) = visible_lights.as_mut() { + visible_lights.entities.clear(); + update_from_light_intersections(&mut visible_lights.entities); + } else { + let mut entities = Vec::new(); + update_from_light_intersections(&mut entities); + commands + .entity(view_entity) + .insert(VisiblePointLights { entities }); } } }