Skip to content
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 respect RenderLayers #5114

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion crates/bevy_sprite/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use bevy_asset::Handle;
use bevy_ecs::bundle::Bundle;
use bevy_render::{
texture::{Image, DEFAULT_IMAGE_HANDLE},
view::Visibility,
view::{ComputedVisibility, Visibility},
};
use bevy_transform::components::{GlobalTransform, Transform};

Expand All @@ -18,6 +18,8 @@ pub struct SpriteBundle {
pub texture: Handle<Image>,
/// User indication of whether an entity is visible
pub visibility: Visibility,
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
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 All @@ -44,4 +47,6 @@ pub struct SpriteSheetBundle {
pub global_transform: GlobalTransform,
/// User indication of whether an entity is visible
pub visibility: Visibility,
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
pub computed_visibility: ComputedVisibility,
}
64 changes: 40 additions & 24 deletions crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use bevy_render::{
render_resource::*,
renderer::{RenderDevice, RenderQueue},
texture::{BevyDefault, Image},
view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility},
view::{ComputedVisibility, Msaa, RenderLayers, ViewUniform, ViewUniformOffset, ViewUniforms},
RenderWorld,
};
use bevy_transform::components::GlobalTransform;
Expand Down Expand Up @@ -185,6 +185,7 @@ pub struct ExtractedSprite {
pub flip_x: bool,
pub flip_y: bool,
pub anchor: Vec2,
pub view_mask: RenderLayers,
}

#[derive(Default)]
Expand Down Expand Up @@ -224,18 +225,25 @@ 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<(
&ComputedVisibility,
&Sprite,
&GlobalTransform,
&Handle<Image>,
Option<&RenderLayers>,
)>,
atlas_query: Query<(
&Visibility,
&ComputedVisibility,
&TextureAtlasSprite,
&GlobalTransform,
&Handle<TextureAtlas>,
Option<&RenderLayers>,
)>,
) {
let mut extracted_sprites = render_world.resource_mut::<ExtractedSprites>();
extracted_sprites.sprites.clear();
for (visibility, sprite, transform, handle) in sprite_query.iter() {
if !visibility.is_visible {
for (computed_visibility, sprite, transform, handle, maybe_view_mask) in sprite_query.iter() {
if !computed_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
Expand All @@ -250,10 +258,13 @@ 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() {
if !visibility.is_visible {
for (computed_visibility, atlas_sprite, transform, texture_atlas_handle, maybe_view_mask) in
atlas_query.iter()
{
if !computed_visibility.is_visible {
continue;
}
if let Some(texture_atlas) = texture_atlases.get(texture_atlas_handle) {
Expand All @@ -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(),
});
}
}
Expand Down Expand Up @@ -347,7 +359,7 @@ 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<(&mut RenderPhase<Transparent2d>, Option<&RenderLayers>)>,
events: Res<SpriteAssetEvents>,
) {
// If an image has changed, the GpuImage has (probably) changed
Expand Down Expand Up @@ -389,39 +401,43 @@ 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;
let extracted_sprites = &mut extracted_sprites.sprites;
// 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,
}
});

// 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),
colored: false,
};
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,
Expand Down
23 changes: 19 additions & 4 deletions crates/bevy_text/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{ComputedVisibility, RenderLayers, Visibility},
RenderWorld,
};
use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas};
use bevy_transform::prelude::{GlobalTransform, Transform};
use bevy_utils::HashSet;
Expand Down Expand Up @@ -58,21 +62,31 @@ pub struct Text2dBundle {
pub text_2d_size: Text2dSize,
pub text_2d_bounds: Text2dBounds,
pub visibility: Visibility,
pub coputed_visibility: Visibility,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub coputed_visibility: Visibility,
pub computed_visibility: Visibility,

}

pub fn extract_text2d_sprite(
mut render_world: ResMut<RenderWorld>,
texture_atlases: Res<Assets<TextureAtlas>>,
text_pipeline: Res<DefaultTextPipeline>,
windows: Res<Windows>,
text2d_query: Query<(Entity, &Visibility, &Text, &GlobalTransform, &Text2dSize)>,
text2d_query: Query<(
Entity,
&ComputedVisibility,
&Text,
&GlobalTransform,
&Text2dSize,
Option<&RenderLayers>,
)>,
) {
let mut extracted_sprites = render_world.resource_mut::<ExtractedSprites>();

let scale_factor = windows.scale_factor(WindowId::primary()) as f32;

for (entity, visibility, text, transform, calculated_size) in text2d_query.iter() {
if !visibility.is_visible {
for (entity, computed_visibility, text, transform, calculated_size, maybe_view_mask) in
text2d_query.iter()
{
if !computed_visibility.is_visible {
continue;
}
let (width, height) = (calculated_size.size.x, calculated_size.size.y);
Expand Down Expand Up @@ -119,6 +133,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(),
});
}
}
Expand Down