From 3441cf222f565e859400d783c3ba75d4618aa2d7 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Mon, 17 Jan 2022 18:53:15 +0100 Subject: [PATCH] bevy_render: Provide a way to opt-out of the built-in frustum culling It breaks the custom instancing in the shader_instancing example if the camera is moved to: 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. --- crates/bevy_render/src/view/visibility/mod.rs | 12 ++++++++++-- examples/shader/shader_instancing.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index 61da101d02d3e..cec6525d1acf2 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 fee46581d4e63..9c5a048ea6107 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