-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sprites and text2d work with RenderLayers (add ComputedVisibility) #4007
Changes from all commits
8bceb1c
6377ee3
1ddb82d
759c292
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,12 +22,12 @@ use bevy_render::{ | |
render_resource::*, | ||
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::FloatOrd; | ||
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<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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ComputedVisibility needs to be used for extraction here too. |
||
&TextureAtlasSprite, | ||
&GlobalTransform, | ||
|
@@ -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 | ||
|
@@ -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<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>>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn’t a map, it’s a set. |
||
) { | ||
// If an image has changed, the GpuImage has (probably) changed | ||
for event in &events.images { | ||
|
@@ -389,11 +400,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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that that suggestion should be an improvement to performance. I want to try to figure out if there is a way to restructure so that the set can be avoided. @james7132 did you ever try using a fixed bit set for visible entities? I seem to remember that you did but I don’t remember. Also, random thought that is not thought through and that may not be good but could be, is it worth storing a fixed bit set of views in which an entity is visible, per entity, instead of a fixed bit set of entities visible per-view? Maybe not as maybe the per-view set is small enough to stay in cache where the per-entity sets would be loaded in as part of iteration… I don’t know. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. VisibleEntities IMO shouldn't, though I haven't tried. It'd require an &Entities on the other end to resolve the Entity from the ID, which may or may not be desirable depending on the downstream use case. |
||
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 | ||
|
@@ -422,6 +435,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, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ComputedVisibility needs to be used for extraction.