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)]
|
||||
#[reflect(Component)]
|
||||
pub struct VisibleEntities {
|
||||
@ -106,7 +110,7 @@ impl Plugin for VisibilityPlugin {
|
||||
pub fn calculate_bounds(
|
||||
mut commands: Commands,
|
||||
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() {
|
||||
if let Some(mesh) = meshes.get(mesh_handle) {
|
||||
@ -142,6 +146,7 @@ pub fn check_visibility(
|
||||
&mut ComputedVisibility,
|
||||
Option<&RenderLayers>,
|
||||
Option<&Aabb>,
|
||||
Option<&NoFrustumCulling>,
|
||||
Option<&GlobalTransform>,
|
||||
)>,
|
||||
)>,
|
||||
@ -161,6 +166,7 @@ pub fn check_visibility(
|
||||
mut computed_visibility,
|
||||
maybe_entity_mask,
|
||||
maybe_aabb,
|
||||
maybe_no_frustum_culling,
|
||||
maybe_transform,
|
||||
) 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 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()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ use bevy::{
|
||||
},
|
||||
render_resource::*,
|
||||
renderer::RenderDevice,
|
||||
view::{ComputedVisibility, ExtractedView, Msaa, Visibility},
|
||||
view::{ComputedVisibility, ExtractedView, Msaa, NoFrustumCulling, Visibility},
|
||||
RenderApp, RenderStage,
|
||||
},
|
||||
};
|
||||
@ -45,6 +45,14 @@ fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
|
||||
),
|
||||
Visibility::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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user