Skip to content

Commit 3c49aab

Browse files
committed
run frustum cumming with parallel iterator
1 parent 83c6ffb commit 3c49aab

File tree

3 files changed

+68
-65
lines changed

3 files changed

+68
-65
lines changed

crates/bevy_render/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.7.0" }
3636
bevy_ecs = { path = "../bevy_ecs", version = "0.7.0" }
3737
bevy_math = { path = "../bevy_math", version = "0.7.0" }
3838
bevy_reflect = { path = "../bevy_reflect", version = "0.7.0", features = ["bevy"] }
39+
bevy_tasks = { path = "../bevy_tasks", version = "0.7.0" }
3940
bevy_transform = { path = "../bevy_transform", version = "0.7.0" }
4041
bevy_window = { path = "../bevy_window", version = "0.7.0" }
4142
bevy_utils = { path = "../bevy_utils", version = "0.7.0" }

crates/bevy_render/src/camera/camera.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,13 @@ impl RenderTarget {
7474
RenderTarget::Window(window_id) => windows
7575
.get(*window_id)
7676
.map(|window| UVec2::new(window.physical_width(), window.physical_height())),
77-
RenderTarget::Image(image_handle) => images.get(image_handle).map(|image| {
78-
let Extent3d { width, height, .. } = image.texture_descriptor.size;
79-
UVec2::new(width, height)
80-
}),
81-
}
82-
.filter(|size| size.x > 0 && size.y > 0)
77+
RenderTarget::Image(image_handle) => images
78+
.get(image_handle)
79+
.map(|image| {
80+
let Extent3d { width, height, .. } = image.texture_descriptor.size;
81+
UVec2::new(width, height)
82+
}),
83+
}.filter(|dim| dim.x > 0 && dim.y > 0)
8384
}
8485
pub fn get_logical_size(&self, windows: &Windows, images: &Assets<Image>) -> Option<Vec2> {
8586
match self {

crates/bevy_render/src/view/visibility/mod.rs

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
mod render_layers;
22

3+
use std::sync::Arc;
4+
35
use bevy_math::Vec3A;
6+
use parking_lot::RwLock;
47
pub use render_layers::*;
58

69
use bevy_app::{CoreStage, Plugin};
@@ -139,72 +142,70 @@ pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
139142
}
140143

141144
pub fn check_visibility(
145+
pool: Res<bevy_tasks::prelude::ComputeTaskPool>,
142146
mut view_query: Query<(&mut VisibleEntities, &Frustum, Option<&RenderLayers>), With<Camera>>,
143-
mut visible_entity_query: ParamSet<(
144-
Query<&mut ComputedVisibility>,
145-
Query<(
146-
Entity,
147-
&Visibility,
148-
&mut ComputedVisibility,
149-
Option<&RenderLayers>,
150-
Option<&Aabb>,
151-
Option<&NoFrustumCulling>,
152-
Option<&GlobalTransform>,
153-
)>,
147+
mut visible_entity_query: Query<(
148+
Entity,
149+
&Visibility,
150+
&mut ComputedVisibility,
151+
Option<&RenderLayers>,
152+
Option<&Aabb>,
153+
Option<&NoFrustumCulling>,
154+
Option<&GlobalTransform>,
154155
)>,
155156
) {
156-
// Reset the computed visibility to false
157-
for mut computed_visibility in visible_entity_query.p0().iter_mut() {
158-
computed_visibility.is_visible = false;
159-
}
160-
161157
for (mut visible_entities, frustum, maybe_view_mask) in view_query.iter_mut() {
162158
visible_entities.entities.clear();
163159
let view_mask = maybe_view_mask.copied().unwrap_or_default();
164160

165-
for (
166-
entity,
167-
visibility,
168-
mut computed_visibility,
169-
maybe_entity_mask,
170-
maybe_aabb,
171-
maybe_no_frustum_culling,
172-
maybe_transform,
173-
) in visible_entity_query.p1().iter_mut()
174-
{
175-
if !visibility.is_visible {
176-
continue;
177-
}
178-
179-
let entity_mask = maybe_entity_mask.copied().unwrap_or_default();
180-
if !view_mask.intersects(&entity_mask) {
181-
continue;
182-
}
183-
184-
// If we have an aabb and transform, do frustum culling
185-
if let (Some(model_aabb), None, Some(transform)) =
186-
(maybe_aabb, maybe_no_frustum_culling, maybe_transform)
187-
{
188-
let model = transform.compute_matrix();
189-
let model_sphere = Sphere {
190-
center: model.transform_point3a(model_aabb.center),
191-
radius: (Vec3A::from(transform.scale) * model_aabb.half_extents).length(),
192-
};
193-
// Do quick sphere-based frustum culling
194-
if !frustum.intersects_sphere(&model_sphere, false) {
195-
continue;
161+
let viz = Arc::new(RwLock::new(Vec::new()));
162+
163+
visible_entity_query.par_for_each_mut(
164+
&pool,
165+
32,
166+
move |(
167+
entity,
168+
visibility,
169+
mut computed_visibility,
170+
maybe_entity_mask,
171+
maybe_aabb,
172+
maybe_no_frustum_culling,
173+
maybe_transform,
174+
)| {
175+
computed_visibility.is_visible = false;
176+
if visibility.is_visible {
177+
let entity_mask = maybe_entity_mask.copied().unwrap_or_default();
178+
if view_mask.intersects(&entity_mask) {
179+
let mut skip = false;
180+
// If we have an aabb and transform, do frustum culling
181+
if let (Some(model_aabb), None, Some(transform)) =
182+
(maybe_aabb, maybe_no_frustum_culling, maybe_transform)
183+
{
184+
let model = transform.compute_matrix();
185+
let model_sphere = Sphere {
186+
center: model.transform_point3a(model_aabb.center),
187+
radius: (Vec3A::from(transform.scale) * model_aabb.half_extents)
188+
.length(),
189+
};
190+
// Do quick sphere-based frustum culling
191+
if !frustum.intersects_sphere(&model_sphere, false) {
192+
skip = true;
193+
}
194+
// If we have an aabb, do aabb-based frustum culling
195+
if !frustum.intersects_obb(model_aabb, &model, false) {
196+
skip = true;
197+
}
198+
}
199+
200+
if !skip {
201+
computed_visibility.is_visible = true;
202+
viz.write().push(entity);
203+
}
204+
}
205+
// TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize
206+
// to prevent holding unneeded memory
196207
}
197-
// If we have an aabb, do aabb-based frustum culling
198-
if !frustum.intersects_obb(model_aabb, &model, false) {
199-
continue;
200-
}
201-
}
202-
203-
computed_visibility.is_visible = true;
204-
visible_entities.entities.push(entity);
205-
}
206-
207-
// TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize
208-
// to prevent holding unneeded memory
208+
},
209+
);
209210
}
210211
}

0 commit comments

Comments
 (0)