bevy_render: Provide a way to opt-out of the built-in frustum culling (#3711)
# Objective
- Allow opting-out of the built-in frustum culling for cases where its behaviour would be incorrect
- Make use of the this in the shader_instancing example that uses a custom instancing method. The built-in frustum culling breaks the custom instancing in the shader_instancing example if the camera is moved to:
```rust
commands.spawn_bundle(PerspectiveCameraBundle {
transform: Transform::from_xyz(12.0, 0.0, 15.0)
.looking_at(Vec3::new(12.0, 0.0, 0.0), Vec3::Y),
..Default::default()
});
```
...such that the Aabb of the cube Mesh that is at the origin goes completely out of view. This incorrectly (for the purpose of the custom instancing) culls the `Mesh` and so culls all instances even though some may be visible.
## Solution
- Add a `NoFrustumCulling` marker component
- Do not compute and add an `Aabb` to `Mesh` entities without an `Aabb` if they have a `NoFrustumCulling` marker component
- Do not apply frustum culling to entities with the `NoFrustumCulling` marker component
This commit is contained in:
parent
e88e394feb
commit
55da315432
@ -40,6 +40,10 @@ impl Default for ComputedVisibility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use this component to opt-out of built-in frustum culling for Mesh entities
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct NoFrustumCulling;
|
||||||
|
|
||||||
#[derive(Clone, Component, Default, Debug, Reflect)]
|
#[derive(Clone, Component, Default, Debug, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct VisibleEntities {
|
pub struct VisibleEntities {
|
||||||
@ -106,7 +110,7 @@ impl Plugin for VisibilityPlugin {
|
|||||||
pub fn calculate_bounds(
|
pub fn calculate_bounds(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
meshes: Res<Assets<Mesh>>,
|
meshes: Res<Assets<Mesh>>,
|
||||||
without_aabb: Query<(Entity, &Handle<Mesh>), Without<Aabb>>,
|
without_aabb: Query<(Entity, &Handle<Mesh>), (Without<Aabb>, Without<NoFrustumCulling>)>,
|
||||||
) {
|
) {
|
||||||
for (entity, mesh_handle) in without_aabb.iter() {
|
for (entity, mesh_handle) in without_aabb.iter() {
|
||||||
if let Some(mesh) = meshes.get(mesh_handle) {
|
if let Some(mesh) = meshes.get(mesh_handle) {
|
||||||
@ -142,6 +146,7 @@ pub fn check_visibility(
|
|||||||
&mut ComputedVisibility,
|
&mut ComputedVisibility,
|
||||||
Option<&RenderLayers>,
|
Option<&RenderLayers>,
|
||||||
Option<&Aabb>,
|
Option<&Aabb>,
|
||||||
|
Option<&NoFrustumCulling>,
|
||||||
Option<&GlobalTransform>,
|
Option<&GlobalTransform>,
|
||||||
)>,
|
)>,
|
||||||
)>,
|
)>,
|
||||||
@ -161,6 +166,7 @@ pub fn check_visibility(
|
|||||||
mut computed_visibility,
|
mut computed_visibility,
|
||||||
maybe_entity_mask,
|
maybe_entity_mask,
|
||||||
maybe_aabb,
|
maybe_aabb,
|
||||||
|
maybe_no_frustum_culling,
|
||||||
maybe_transform,
|
maybe_transform,
|
||||||
) in visible_entity_query.q1().iter_mut()
|
) in visible_entity_query.q1().iter_mut()
|
||||||
{
|
{
|
||||||
@ -174,7 +180,9 @@ pub fn check_visibility(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have an aabb and transform, do frustum culling
|
// If we have an aabb and transform, do frustum culling
|
||||||
if let (Some(aabb), Some(transform)) = (maybe_aabb, maybe_transform) {
|
if let (Some(aabb), None, Some(transform)) =
|
||||||
|
(maybe_aabb, maybe_no_frustum_culling, maybe_transform)
|
||||||
|
{
|
||||||
if !frustum.intersects_obb(aabb, &transform.compute_matrix()) {
|
if !frustum.intersects_obb(aabb, &transform.compute_matrix()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
render_resource::*,
|
render_resource::*,
|
||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
view::{ComputedVisibility, ExtractedView, Msaa, Visibility},
|
view::{ComputedVisibility, ExtractedView, Msaa, NoFrustumCulling, Visibility},
|
||||||
RenderApp, RenderStage,
|
RenderApp, RenderStage,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -45,6 +45,14 @@ fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
|
|||||||
),
|
),
|
||||||
Visibility::default(),
|
Visibility::default(),
|
||||||
ComputedVisibility::default(),
|
ComputedVisibility::default(),
|
||||||
|
// NOTE: Frustum culling is done based on the Aabb of the Mesh and the GlobalTransform.
|
||||||
|
// As the cube is at the origin, if its Aabb moves outside the view frustum, all the
|
||||||
|
// instanced cubes will be culled.
|
||||||
|
// The InstanceMaterialData contains the 'GlobalTransform' information for this custom
|
||||||
|
// instancing, and that is not taken into account with the built-in frustum culling.
|
||||||
|
// We must disable the built-in frustum culling by adding the `NoFrustumCulling` marker
|
||||||
|
// component to avoid incorrect culling.
|
||||||
|
NoFrustumCulling,
|
||||||
));
|
));
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user