From eba2ecbfd9570d16183cae6668748d5d9f627e71 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Sun, 20 Feb 2022 22:05:34 +0100 Subject: [PATCH] Squash pr #4007 Quick and dirty ComputedVisiblity support for sprites, text2d This is needed for RenderLayers to work properly Use a HashSet to speed up visibility checking Remove resolved todo Don't reallocate visible sprite entities map every frame --- crates/bevy_sprite/src/bundle.rs | 3 +++ crates/bevy_sprite/src/render/mod.rs | 32 +++++++++++++++++++++------- crates/bevy_text/src/text2d.rs | 4 +++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/crates/bevy_sprite/src/bundle.rs b/crates/bevy_sprite/src/bundle.rs index 82fdcd9db62928..4400f6c26de731 100644 --- a/crates/bevy_sprite/src/bundle.rs +++ b/crates/bevy_sprite/src/bundle.rs @@ -5,6 +5,7 @@ use crate::{ use bevy_asset::Handle; use bevy_ecs::bundle::Bundle; use bevy_render::{ + prelude::ComputedVisibility, texture::{Image, DEFAULT_IMAGE_HANDLE}, view::Visibility, }; @@ -18,6 +19,7 @@ pub struct SpriteBundle { pub texture: Handle, /// User indication of whether an entity is visible pub visibility: Visibility, + pub computed_visibility: ComputedVisibility, } impl Default for SpriteBundle { @@ -28,6 +30,7 @@ impl Default for SpriteBundle { global_transform: Default::default(), texture: DEFAULT_IMAGE_HANDLE.typed(), visibility: Default::default(), + computed_visibility: Default::default(), } } } diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 577f9da4d855fb..8dcd40cb8b258c 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -23,11 +23,11 @@ use bevy_render::{ render_resource::{std140::AsStd140, *}, renderer::{RenderDevice, RenderQueue}, texture::{BevyDefault, Image}, - view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility}, + view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility, VisibleEntities}, RenderWorld, }; use bevy_transform::components::GlobalTransform; -use bevy_utils::HashMap; +use bevy_utils::{HashMap, HashSet}; use bytemuck::{Pod, Zeroable}; use copyless::VecHelper; @@ -173,6 +173,7 @@ impl SpecializedRenderPipeline for SpritePipeline { #[derive(Component, Clone, Copy)] pub struct ExtractedSprite { + pub entity: Entity, pub transform: GlobalTransform, pub color: Color, /// Select an area of the texture @@ -224,8 +225,15 @@ 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<( + Entity, + &Visibility, + &Sprite, + &GlobalTransform, + &Handle, + )>, atlas_query: Query<( + Entity, &Visibility, &TextureAtlasSprite, &GlobalTransform, @@ -234,12 +242,13 @@ pub fn extract_sprites( ) { let mut extracted_sprites = render_world.resource_mut::(); extracted_sprites.sprites.clear(); - for (visibility, sprite, transform, handle) in sprite_query.iter() { + for (entity, visibility, sprite, transform, handle) in sprite_query.iter() { if !visibility.is_visible { continue; } // PERF: we don't check in this function that the `Image` asset is ready, since it should be in most cases and hashing the handle is expensive extracted_sprites.sprites.alloc().init(ExtractedSprite { + entity, color: sprite.color, transform: *transform, // Use the full texture @@ -252,13 +261,14 @@ pub fn extract_sprites( anchor: sprite.anchor.as_vec(), }); } - for (visibility, atlas_sprite, transform, texture_atlas_handle) in atlas_query.iter() { + for (entity, visibility, atlas_sprite, transform, texture_atlas_handle) in atlas_query.iter() { if !visibility.is_visible { continue; } if let Some(texture_atlas) = texture_atlases.get(texture_atlas_handle) { let rect = Some(texture_atlas.textures[atlas_sprite.index as usize]); extracted_sprites.sprites.alloc().init(ExtractedSprite { + entity, color: atlas_sprite.color, transform: *transform, // Select the area in the texture atlas @@ -347,8 +357,9 @@ pub fn queue_sprites( gpu_images: Res>, msaa: Res, mut extracted_sprites: ResMut, - mut views: Query<&mut RenderPhase>, + mut views: Query<(&VisibleEntities, &mut RenderPhase)>, events: Res, + mut visible_entities_map: Local>, ) { // If an image has changed, the GpuImage has (probably) changed for event in &events.images { @@ -388,11 +399,13 @@ 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() { + for (visible_entities, mut transparent_phase) in views.iter_mut() { let extracted_sprites = &mut extracted_sprites.sprites; let image_bind_groups = &mut *image_bind_groups; + visible_entities_map.clear(); + visible_entities_map.extend(visible_entities.iter().copied()); + transparent_phase.items.reserve(extracted_sprites.len()); // Sort sprites by z for correct transparency and then by handle to improve batching @@ -421,6 +434,9 @@ pub fn queue_sprites( // 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 !visible_entities_map.contains(&extracted_sprite.entity) { + 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 9bab65aa982970..d4e98d97ff9c5c 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -9,7 +9,7 @@ use bevy_ecs::{ }; use bevy_math::{Size, Vec3}; use bevy_reflect::Reflect; -use bevy_render::{texture::Image, view::Visibility, RenderWorld}; +use bevy_render::{prelude::ComputedVisibility, texture::Image, view::Visibility, RenderWorld}; use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas}; use bevy_transform::prelude::{GlobalTransform, Transform}; use bevy_window::{WindowId, Windows}; @@ -56,6 +56,7 @@ pub struct Text2dBundle { pub text_2d_size: Text2dSize, pub text_2d_bounds: Text2dBounds, pub visibility: Visibility, + pub computed_visibility: ComputedVisibility, } pub fn extract_text2d_sprite( @@ -109,6 +110,7 @@ pub fn extract_text2d_sprite( let transform = text_transform.mul_transform(glyph_transform); extracted_sprites.sprites.push(ExtractedSprite { + entity, transform, color, rect,