|
1 | 1 | mod render_layers;
|
2 | 2 |
|
| 3 | +use std::sync::Arc; |
| 4 | + |
3 | 5 | use bevy_math::Vec3A;
|
| 6 | +use parking_lot::RwLock; |
4 | 7 | pub use render_layers::*;
|
5 | 8 |
|
6 | 9 | use bevy_app::{CoreStage, Plugin};
|
@@ -139,72 +142,70 @@ pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
|
139 | 142 | }
|
140 | 143 |
|
141 | 144 | pub fn check_visibility(
|
| 145 | + pool: Res<bevy_tasks::prelude::ComputeTaskPool>, |
142 | 146 | 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>, |
154 | 155 | )>,
|
155 | 156 | ) {
|
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 |
| - |
161 | 157 | for (mut visible_entities, frustum, maybe_view_mask) in view_query.iter_mut() {
|
162 | 158 | visible_entities.entities.clear();
|
163 | 159 | let view_mask = maybe_view_mask.copied().unwrap_or_default();
|
164 | 160 |
|
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 |
196 | 207 | }
|
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 | + ); |
209 | 210 | }
|
210 | 211 | }
|
0 commit comments