Skip to content

Commit

Permalink
Squash pr bevyengine#4007
Browse files Browse the repository at this point in the history
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
  • Loading branch information
johanhelsing authored and TethysSvensson committed Apr 5, 2022
1 parent cf831d5 commit eba2ecb
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
3 changes: 3 additions & 0 deletions crates/bevy_sprite/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -18,6 +19,7 @@ pub struct SpriteBundle {
pub texture: Handle<Image>,
/// User indication of whether an entity is visible
pub visibility: Visibility,
pub computed_visibility: ComputedVisibility,
}

impl Default for SpriteBundle {
Expand All @@ -28,6 +30,7 @@ impl Default for SpriteBundle {
global_transform: Default::default(),
texture: DEFAULT_IMAGE_HANDLE.typed(),
visibility: Default::default(),
computed_visibility: Default::default(),
}
}
}
Expand Down
32 changes: 24 additions & 8 deletions crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -224,8 +225,15 @@ pub fn extract_sprite_events(
pub fn extract_sprites(
mut render_world: ResMut<RenderWorld>,
texture_atlases: Res<Assets<TextureAtlas>>,
sprite_query: Query<(&Visibility, &Sprite, &GlobalTransform, &Handle<Image>)>,
sprite_query: Query<(
Entity,
&Visibility,
&Sprite,
&GlobalTransform,
&Handle<Image>,
)>,
atlas_query: Query<(
Entity,
&Visibility,
&TextureAtlasSprite,
&GlobalTransform,
Expand All @@ -234,12 +242,13 @@ pub fn extract_sprites(
) {
let mut extracted_sprites = render_world.resource_mut::<ExtractedSprites>();
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
Expand All @@ -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
Expand Down Expand Up @@ -347,8 +357,9 @@ pub fn queue_sprites(
gpu_images: Res<RenderAssets<Image>>,
msaa: Res<Msaa>,
mut extracted_sprites: ResMut<ExtractedSprites>,
mut views: Query<&mut RenderPhase<Transparent2d>>,
mut views: Query<(&VisibleEntities, &mut RenderPhase<Transparent2d>)>,
events: Res<SpriteAssetEvents>,
mut visible_entities_map: Local<HashSet<Entity>>,
) {
// If an image has changed, the GpuImage has (probably) changed
for event in &events.images {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_text/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit eba2ecb

Please sign in to comment.