Fix rendering of sprites, text, and meshlets after #12582. (#12945)

`Sprite`, `Text`, and `Handle<MeshletMesh>` were types of renderable
entities that the new segregated visible entity system didn't handle, so
they didn't appear.

Because `bevy_text` depends on `bevy_sprite`, and the visibility
computation of text happens in the latter crate, I had to introduce a
new marker component, `SpriteSource`. `SpriteSource` marks entities that
aren't themselves sprites but become sprites during rendering. I added
this component to `Text2dBundle`. Unfortunately, this is technically a
breaking change, although I suspect it won't break anybody in practice
except perhaps editors.

Fixes #12935.

## Changelog

### Changed

* `Text2dBundle` now includes a new marker component, `SpriteSource`.
Bevy uses this internally to optimize visibility calculation.

## Migration Guide

* `Text` now requires a `SpriteSource` marker component in order to
appear. This component has been added to `Text2dBundle`.
This commit is contained in:
Patrick Walton 2024-04-13 09:15:00 -05:00 committed by GitHub
parent ae9775c83b
commit 8577a448f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 75 additions and 13 deletions

View File

@ -56,7 +56,7 @@ use self::{
visibility_buffer_raster_node::MeshletVisibilityBufferRasterPassNode, visibility_buffer_raster_node::MeshletVisibilityBufferRasterPassNode,
}; };
use crate::{graph::NodePbr, Material}; use crate::{graph::NodePbr, Material};
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin, PostUpdate};
use bevy_asset::{load_internal_asset, AssetApp, Handle}; use bevy_asset::{load_internal_asset, AssetApp, Handle};
use bevy_core_pipeline::{ use bevy_core_pipeline::{
core_3d::{ core_3d::{
@ -68,6 +68,7 @@ use bevy_core_pipeline::{
use bevy_ecs::{ use bevy_ecs::{
bundle::Bundle, bundle::Bundle,
entity::Entity, entity::Entity,
prelude::With,
query::Has, query::Has,
schedule::IntoSystemConfigs, schedule::IntoSystemConfigs,
system::{Commands, Query}, system::{Commands, Query},
@ -75,10 +76,14 @@ use bevy_ecs::{
use bevy_render::{ use bevy_render::{
render_graph::{RenderGraphApp, ViewNodeRunner}, render_graph::{RenderGraphApp, ViewNodeRunner},
render_resource::{Shader, TextureUsages}, render_resource::{Shader, TextureUsages},
view::{prepare_view_targets, InheritedVisibility, Msaa, ViewVisibility, Visibility}, view::{
check_visibility, prepare_view_targets, InheritedVisibility, Msaa, ViewVisibility,
Visibility, VisibilitySystems,
},
ExtractSchedule, Render, RenderApp, RenderSet, ExtractSchedule, Render, RenderApp, RenderSet,
}; };
use bevy_transform::components::{GlobalTransform, Transform}; use bevy_transform::components::{GlobalTransform, Transform};
use bevy_transform::TransformSystem;
const MESHLET_BINDINGS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(1325134235233421); const MESHLET_BINDINGS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(1325134235233421);
const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle<Shader> = const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle<Shader> =
@ -160,7 +165,18 @@ impl Plugin for MeshletPlugin {
app.init_asset::<MeshletMesh>() app.init_asset::<MeshletMesh>()
.register_asset_loader(MeshletMeshSaverLoad) .register_asset_loader(MeshletMeshSaverLoad)
.insert_resource(Msaa::Off); .insert_resource(Msaa::Off)
.add_systems(
PostUpdate,
check_visibility::<WithMeshletMesh>
.in_set(VisibilitySystems::CheckVisibility)
.after(VisibilitySystems::CalculateBounds)
.after(VisibilitySystems::UpdateOrthographicFrusta)
.after(VisibilitySystems::UpdatePerspectiveFrusta)
.after(VisibilitySystems::UpdateProjectionFrusta)
.after(VisibilitySystems::VisibilityPropagate)
.after(TransformSystem::TransformPropagate),
);
} }
fn finish(&self, app: &mut App) { fn finish(&self, app: &mut App) {
@ -248,6 +264,10 @@ impl<M: Material> Default for MaterialMeshletMeshBundle<M> {
} }
} }
/// A convenient alias for `With<Handle<MeshletMesh>>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithMeshletMesh = With<Handle<MeshletMesh>>;
fn configure_meshlet_views( fn configure_meshlet_views(
mut views_3d: Query<( mut views_3d: Query<(
Entity, Entity,

View File

@ -32,6 +32,7 @@ pub mod prelude {
}; };
} }
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_transform::TransformSystem; use bevy_transform::TransformSystem;
pub use bundle::*; pub use bundle::*;
pub use dynamic_texture_atlas_builder::*; pub use dynamic_texture_atlas_builder::*;
@ -45,8 +46,9 @@ pub use texture_slice::*;
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, AssetApp, Assets, Handle}; use bevy_asset::{load_internal_asset, AssetApp, Assets, Handle};
use bevy_core_pipeline::core_2d::Transparent2d; use bevy_core_pipeline::core_2d::Transparent2d;
use bevy_ecs::prelude::*; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_render::{ use bevy_render::{
extract_component::{ExtractComponent, ExtractComponentPlugin},
mesh::Mesh, mesh::Mesh,
primitives::Aabb, primitives::Aabb,
render_phase::AddRenderCommand, render_phase::AddRenderCommand,
@ -69,6 +71,22 @@ pub enum SpriteSystem {
ComputeSlices, ComputeSlices,
} }
/// A component that marks entities that aren't themselves sprites but become
/// sprites during rendering.
///
/// Right now, this is used for `Text`.
#[derive(Component, Reflect, Clone, Copy, Debug, Default)]
#[reflect(Component, Default)]
pub struct SpriteSource;
/// A convenient alias for `With<Mesh2dHandle>>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithMesh2d = With<Mesh2dHandle>;
/// A convenient alias for `Or<With<Sprite>, With<SpriteSource>>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithSprite = Or<(With<Sprite>, With<SpriteSource>)>;
impl Plugin for SpritePlugin { impl Plugin for SpritePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( load_internal_asset!(
@ -85,7 +103,12 @@ impl Plugin for SpritePlugin {
.register_type::<Anchor>() .register_type::<Anchor>()
.register_type::<TextureAtlas>() .register_type::<TextureAtlas>()
.register_type::<Mesh2dHandle>() .register_type::<Mesh2dHandle>()
.add_plugins((Mesh2dRenderPlugin, ColorMaterialPlugin)) .register_type::<SpriteSource>()
.add_plugins((
Mesh2dRenderPlugin,
ColorMaterialPlugin,
ExtractComponentPlugin::<SpriteSource>::default(),
))
.add_systems( .add_systems(
PostUpdate, PostUpdate,
( (
@ -95,7 +118,10 @@ impl Plugin for SpritePlugin {
compute_slices_on_sprite_change, compute_slices_on_sprite_change,
) )
.in_set(SpriteSystem::ComputeSlices), .in_set(SpriteSystem::ComputeSlices),
check_visibility::<WithMesh2d> (
check_visibility::<WithMesh2d>,
check_visibility::<WithSprite>,
)
.in_set(VisibilitySystems::CheckVisibility) .in_set(VisibilitySystems::CheckVisibility)
.after(VisibilitySystems::CalculateBounds) .after(VisibilitySystems::CalculateBounds)
.after(VisibilitySystems::UpdateOrthographicFrusta) .after(VisibilitySystems::UpdateOrthographicFrusta)
@ -185,6 +211,18 @@ pub fn calculate_bounds_2d(
} }
} }
impl ExtractComponent for SpriteSource {
type QueryData = ();
type QueryFilter = ();
type Out = SpriteSource;
fn extract_component(_: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
Some(SpriteSource)
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {

View File

@ -48,10 +48,6 @@ impl From<Handle<Mesh>> for Mesh2dHandle {
} }
} }
/// A convenient alias for `With<Mesh2dHandle>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithMesh2d = With<Mesh2dHandle>;
#[derive(Default)] #[derive(Default)]
pub struct Mesh2dRenderPlugin; pub struct Mesh2dRenderPlugin;

View File

@ -2,7 +2,7 @@ use std::ops::Range;
use crate::{ use crate::{
texture_atlas::{TextureAtlas, TextureAtlasLayout}, texture_atlas::{TextureAtlas, TextureAtlasLayout},
ComputedTextureSlices, Sprite, WithMesh2d, SPRITE_SHADER_HANDLE, ComputedTextureSlices, Sprite, WithSprite, SPRITE_SHADER_HANDLE,
}; };
use bevy_asset::{AssetEvent, AssetId, Assets, Handle}; use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
use bevy_color::LinearRgba; use bevy_color::LinearRgba;
@ -490,7 +490,7 @@ pub fn queue_sprites(
view_entities.clear(); view_entities.clear();
view_entities.extend( view_entities.extend(
visible_entities visible_entities
.iter::<WithMesh2d>() .iter::<WithSprite>()
.map(|e| e.index() as usize), .map(|e| e.index() as usize),
); );

View File

@ -78,6 +78,10 @@ pub enum YAxisOrientation {
BottomToTop, BottomToTop,
} }
/// A convenient alias for `With<Text>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithText = With<Text>;
impl Plugin for TextPlugin { impl Plugin for TextPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_asset::<Font>() app.init_asset::<Font>()

View File

@ -23,7 +23,7 @@ use bevy_render::{
view::{InheritedVisibility, NoFrustumCulling, ViewVisibility, Visibility}, view::{InheritedVisibility, NoFrustumCulling, ViewVisibility, Visibility},
Extract, Extract,
}; };
use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlasLayout}; use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, SpriteSource, TextureAtlasLayout};
use bevy_transform::prelude::{GlobalTransform, Transform}; use bevy_transform::prelude::{GlobalTransform, Transform};
use bevy_utils::HashSet; use bevy_utils::HashSet;
use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged}; use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
@ -78,6 +78,10 @@ pub struct Text2dBundle {
pub view_visibility: ViewVisibility, pub view_visibility: ViewVisibility,
/// Contains the size of the text and its glyph's position and scale data. Generated via [`TextPipeline::queue_text`] /// Contains the size of the text and its glyph's position and scale data. Generated via [`TextPipeline::queue_text`]
pub text_layout_info: TextLayoutInfo, pub text_layout_info: TextLayoutInfo,
/// Marks that this is a [`SpriteSource`].
///
/// This is needed for visibility computation to work properly.
pub sprite_source: SpriteSource,
} }
/// This system extracts the sprites from the 2D text components and adds them to the /// This system extracts the sprites from the 2D text components and adds them to the