diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 06f8ebf818f7e..e07ceaec78048 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -3,7 +3,7 @@ use crate::{ prelude::Image, render_asset::RenderAssets, render_resource::TextureView, - view::{ExtractedView, ExtractedWindows, VisibleEntities}, + view::{ExtractedView, ExtractedWindows, RenderLayers, VisibleEntities}, }; use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_derive::{Deref, DerefMut}; @@ -404,9 +404,12 @@ pub fn extract_cameras( &CameraRenderGraph, &GlobalTransform, &VisibleEntities, + Option<&RenderLayers>, )>, ) { - for (entity, camera, camera_render_graph, transform, visible_entities) in query.iter() { + for (entity, camera, camera_render_graph, transform, visible_entities, maybe_view_mask) in + query.iter() + { if !camera.is_active { continue; } @@ -433,6 +436,7 @@ pub fn extract_cameras( height: viewport_size.y, }, visible_entities.clone(), + maybe_view_mask.cloned().unwrap_or_default(), )); } } diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index c0066482014f7..f5b5c238f6f4d 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -22,7 +22,7 @@ use bevy_render::{ render_resource::*, renderer::{RenderDevice, RenderQueue}, texture::{BevyDefault, Image}, - view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility}, + view::{Msaa, RenderLayers, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility}, RenderWorld, }; use bevy_transform::components::GlobalTransform; @@ -185,6 +185,7 @@ pub struct ExtractedSprite { pub flip_x: bool, pub flip_y: bool, pub anchor: Vec2, + pub view_mask: RenderLayers, } #[derive(Default)] @@ -224,17 +225,24 @@ pub fn extract_sprite_events( pub fn extract_sprites( mut render_world: ResMut, texture_atlases: Res>, - sprite_query: Query<(&Visibility, &Sprite, &GlobalTransform, &Handle)>, + sprite_query: Query<( + &Visibility, + &Sprite, + &GlobalTransform, + &Handle, + Option<&RenderLayers>, + )>, atlas_query: Query<( &Visibility, &TextureAtlasSprite, &GlobalTransform, &Handle, + Option<&RenderLayers>, )>, ) { let mut extracted_sprites = render_world.resource_mut::(); extracted_sprites.sprites.clear(); - for (visibility, sprite, transform, handle) in sprite_query.iter() { + for (visibility, sprite, transform, handle, maybe_view_mask) in sprite_query.iter() { if !visibility.is_visible { continue; } @@ -250,9 +258,12 @@ pub fn extract_sprites( flip_y: sprite.flip_y, image_handle_id: handle.id, anchor: sprite.anchor.as_vec(), + view_mask: maybe_view_mask.copied().unwrap_or_default(), }); } - for (visibility, atlas_sprite, transform, texture_atlas_handle) in atlas_query.iter() { + for (visibility, atlas_sprite, transform, texture_atlas_handle, maybe_view_mask) in + atlas_query.iter() + { if !visibility.is_visible { continue; } @@ -269,6 +280,7 @@ pub fn extract_sprites( flip_y: atlas_sprite.flip_y, image_handle_id: texture_atlas.texture.id, anchor: atlas_sprite.anchor.as_vec(), + view_mask: maybe_view_mask.copied().unwrap_or_default(), }); } } @@ -347,7 +359,7 @@ pub fn queue_sprites( gpu_images: Res>, msaa: Res, mut extracted_sprites: ResMut, - mut views: Query<&mut RenderPhase>, + mut views: Query<(&mut RenderPhase, Option<&RenderLayers>)>, events: Res, ) { // If an image has changed, the GpuImage has (probably) changed @@ -389,26 +401,26 @@ pub fn queue_sprites( let mut index = 0; let mut colored_index = 0; - // FIXME: VisibleEntities is ignored - for mut transparent_phase in views.iter_mut() { - let extracted_sprites = &mut extracted_sprites.sprites; + // Sort sprites by z for correct transparency and then by handle to improve batching + extracted_sprites.sprites.sort_unstable_by(|a, b| { + match a + .transform + .translation + .z + .partial_cmp(&b.transform.translation.z) + { + Some(Ordering::Equal) | None => a.image_handle_id.cmp(&b.image_handle_id), + Some(other) => other, + } + }); + let extracted_sprites = &extracted_sprites.sprites; + + // PERF: VisibleEntities is ignored and view_mask is used directly + for (mut transparent_phase, maybe_view_mask) in views.iter_mut() { let image_bind_groups = &mut *image_bind_groups; transparent_phase.items.reserve(extracted_sprites.len()); - // Sort sprites by z for correct transparency and then by handle to improve batching - extracted_sprites.sort_unstable_by(|a, b| { - match a - .transform - .translation - .z - .partial_cmp(&b.transform.translation.z) - { - Some(Ordering::Equal) | None => a.image_handle_id.cmp(&b.image_handle_id), - Some(other) => other, - } - }); - // Impossible starting values that will be replaced on the first iteration let mut current_batch = SpriteBatch { image_handle_id: HandleId::Id(Uuid::nil(), u64::MAX), @@ -416,12 +428,16 @@ pub fn queue_sprites( }; let mut current_batch_entity = Entity::from_raw(u32::MAX); let mut current_image_size = Vec2::ZERO; + let view_mask = maybe_view_mask.copied().unwrap_or_default(); // Add a phase item for each sprite, and detect when succesive items can be batched. // Spawn an entity with a `SpriteBatch` component for each possible batch. // Compatible items share the same entity. // Batches are merged later (in `batch_phase_system()`), so that they can be interrupted // by any other phase item (and they can interrupt other items from batching). for extracted_sprite in extracted_sprites.iter() { + if !view_mask.intersects(&extracted_sprite.view_mask) { + continue; + } let new_batch = SpriteBatch { image_handle_id: extracted_sprite.image_handle_id, colored: extracted_sprite.color != Color::WHITE, diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index d0bebbad3609a..46e1d088de6c2 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -10,7 +10,11 @@ use bevy_ecs::{ }; use bevy_math::{Vec2, Vec3}; use bevy_reflect::Reflect; -use bevy_render::{texture::Image, view::Visibility, RenderWorld}; +use bevy_render::{ + texture::Image, + view::{RenderLayers, Visibility}, + RenderWorld, +}; use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas}; use bevy_transform::prelude::{GlobalTransform, Transform}; use bevy_utils::HashSet; @@ -65,13 +69,22 @@ pub fn extract_text2d_sprite( texture_atlases: Res>, text_pipeline: Res, windows: Res, - text2d_query: Query<(Entity, &Visibility, &Text, &GlobalTransform, &Text2dSize)>, + text2d_query: Query<( + Entity, + &Visibility, + &Text, + &GlobalTransform, + &Text2dSize, + Option<&RenderLayers>, + )>, ) { let mut extracted_sprites = render_world.resource_mut::(); let scale_factor = windows.scale_factor(WindowId::primary()) as f32; - for (entity, visibility, text, transform, calculated_size) in text2d_query.iter() { + for (entity, visibility, text, transform, calculated_size, maybe_view_mask) in + text2d_query.iter() + { if !visibility.is_visible { continue; } @@ -119,6 +132,7 @@ pub fn extract_text2d_sprite( flip_x: false, flip_y: false, anchor: Anchor::Center.as_vec(), + view_mask: maybe_view_mask.copied().unwrap_or_default(), }); } }