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 all commits
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
8 changes: 6 additions & 2 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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;
}
Expand All @@ -433,6 +436,7 @@ pub fn extract_cameras(
height: viewport_size.y,
},
visible_entities.clone(),
maybe_view_mask.cloned().unwrap_or_default(),
));
}
}
Expand Down
58 changes: 37 additions & 21 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::{Msaa, RenderLayers, ViewUniform, ViewUniformOffset, ViewUniforms, Visibility},
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,17 +225,24 @@ 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<(
&Visibility,
&Sprite,
&GlobalTransform,
&Handle<Image>,
Option<&RenderLayers>,
)>,
atlas_query: Query<(
&Visibility,
&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() {
for (visibility, sprite, transform, handle, maybe_view_mask) in sprite_query.iter() {
if !visibility.is_visible {
continue;
}
Expand All @@ -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;
}
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;
// 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),
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
20 changes: 17 additions & 3 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::{RenderLayers, Visibility},
RenderWorld,
};
use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas};
use bevy_transform::prelude::{GlobalTransform, Transform};
use bevy_utils::HashSet;
Expand Down Expand Up @@ -65,13 +69,22 @@ pub fn extract_text2d_sprite(
texture_atlases: Res<Assets<TextureAtlas>>,
text_pipeline: Res<DefaultTextPipeline>,
windows: Res<Windows>,
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::<ExtractedSprites>();

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;
}
Expand Down Expand Up @@ -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(),
});
}
}
Expand Down