diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index 61da101d02..cec6525d1a 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -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>, - without_aabb: Query<(Entity, &Handle), Without>, + without_aabb: Query<(Entity, &Handle), (Without, Without)>, ) { 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; } diff --git a/examples/shader/shader_instancing.rs b/examples/shader/shader_instancing.rs index fee46581d4..9c5a048ea6 100644 --- a/examples/shader/shader_instancing.rs +++ b/examples/shader/shader_instancing.rs @@ -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>) { ), 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