diff --git a/crates/bevy_sprite/src/entity.rs b/crates/bevy_sprite/src/entity.rs index 9136cce5ed598e..6f278323273ab7 100644 --- a/crates/bevy_sprite/src/entity.rs +++ b/crates/bevy_sprite/src/entity.rs @@ -1,6 +1,6 @@ use crate::{ render::SPRITE_PIPELINE_HANDLE, sprite::Sprite, ColorMaterial, TextureAtlas, - TextureAtlasSprite, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE, + TextureAtlasSprite, TextureAtlasSpriteScale, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE, }; use bevy_asset::Handle; use bevy_ecs::Bundle; @@ -52,6 +52,7 @@ impl Default for SpriteBundle { pub struct SpriteSheetBundle { /// The specific sprite from the texture atlas to be drawn pub sprite: TextureAtlasSprite, + pub scale: TextureAtlasSpriteScale, /// A handle to the texture atlas that holds the sprite images pub texture_atlas: Handle, /// Data pertaining to how the sprite is drawn on the screen @@ -78,6 +79,7 @@ impl Default for SpriteSheetBundle { mesh: QUAD_HANDLE.typed(), draw: Default::default(), sprite: Default::default(), + scale: Default::default(), texture_atlas: Default::default(), transform: Default::default(), global_transform: Default::default(), diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 221df7cb95091c..570e6faa7425e7 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -1,4 +1,4 @@ -use crate::{ColorMaterial, Sprite, TextureAtlas, TextureAtlasSprite}; +use crate::{ColorMaterial, Sprite, TextureAtlas, TextureAtlasSprite, TextureAtlasSpriteScale}; use bevy_asset::{Assets, HandleUntyped}; use bevy_ecs::Resources; use bevy_reflect::TypeUuid; @@ -119,6 +119,7 @@ pub mod node { pub const COLOR_MATERIAL: &str = "color_material"; pub const SPRITE: &str = "sprite"; pub const SPRITE_SHEET: &str = "sprite_sheet"; + pub const SPRITE_SHEET_SCALE: &str = "sprite_sheet_scale"; pub const SPRITE_SHEET_SPRITE: &str = "sprite_sheet_sprite"; } @@ -149,6 +150,11 @@ impl SpriteRenderGraphBuilder for RenderGraph { RenderResourcesNode::::new(true), ); + self.add_system_node( + node::SPRITE_SHEET_SCALE, + RenderResourcesNode::::new(true), + ); + let mut pipelines = resources.get_mut::>().unwrap(); let mut shaders = resources.get_mut::>().unwrap(); pipelines.set_untracked(SPRITE_PIPELINE_HANDLE, build_sprite_pipeline(&mut shaders)); diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index d967ac5411ba3c..c9fff68f491975 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -35,9 +35,13 @@ layout(set = 2, binding = 1) uniform TextureAtlasSprite { uint TextureAtlasSprite_index; }; +layout(set = 2, binding = 2) uniform TextureAtlasSpriteScale { + vec2 SpriteScale; +}; + void main() { Rect sprite_rect = Textures[TextureAtlasSprite_index]; - vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin; + vec2 sprite_dimensions = (sprite_rect.end - sprite_rect.begin)*SpriteScale; vec3 vertex_position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); vec2 atlas_positions[4] = vec2[]( vec2(sprite_rect.begin.x, sprite_rect.end.y), diff --git a/crates/bevy_sprite/src/texture_atlas.rs b/crates/bevy_sprite/src/texture_atlas.rs index c78d398432fd3c..a6e6f472d138a3 100644 --- a/crates/bevy_sprite/src/texture_atlas.rs +++ b/crates/bevy_sprite/src/texture_atlas.rs @@ -52,6 +52,28 @@ impl TextureAtlasSprite { } } +#[derive(Debug, RenderResources, RenderResource)] +#[render_resources(from_self)] +pub struct TextureAtlasSpriteScale { + pub scale: Vec2, +} + +impl Default for TextureAtlasSpriteScale { + fn default() -> Self { + Self { + scale: Vec2::splat(1.), + } + } +} + +unsafe impl Byteable for TextureAtlasSpriteScale {} + +impl TextureAtlasSpriteScale { + pub fn new(scale: Vec2) -> TextureAtlasSpriteScale { + Self { scale } + } +} + impl TextureAtlas { /// Create a new `TextureAtlas` that has a texture, but does not have /// any individual sprites specified diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index c92aa889d20d93..a216dfffdce6ac 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -1,4 +1,4 @@ -use bevy_math::{Mat4, Vec3}; +use bevy_math::{Mat4, Vec2, Vec3}; use bevy_render::{ color::Color, draw::{Draw, DrawContext, DrawError, Drawable}, @@ -48,6 +48,7 @@ impl Default for TextStyle { pub struct DrawableText<'a> { pub render_resource_bindings: &'a mut RenderResourceBindings, pub position: Vec3, + pub inv_scale_factor: f32, pub style: &'a TextStyle, pub text_glyphs: &'a Vec, pub msaa: &'a Msaa, @@ -97,6 +98,8 @@ impl<'a> Drawable for DrawableText<'a> { // set global bindings context.set_bind_groups_from_bindings(draw, &mut [self.render_resource_bindings])?; + let scale = Vec2::splat(self.inv_scale_factor); + for tv in self.text_glyphs { context.set_asset_bind_groups(draw, &tv.atlas_info.texture_atlas)?; @@ -105,13 +108,17 @@ impl<'a> Drawable for DrawableText<'a> { color: self.style.color, }; - let transform = Mat4::from_translation(self.position + tv.position.extend(0.)); + let transform = Mat4::from_translation( + self.position + (tv.position * self.inv_scale_factor).extend(0.), + ); let transform_buffer = context.get_uniform_buffer(&transform).unwrap(); let sprite_buffer = context.get_uniform_buffer(&sprite).unwrap(); + let scale_buffer = context.get_uniform_buffer(&scale).unwrap(); let sprite_bind_group = BindGroup::build() .add_binding(0, transform_buffer) .add_binding(1, sprite_buffer) + .add_binding(2, scale_buffer) .finish(); context.create_bind_group_resource(2, &sprite_bind_group)?; draw.set_bind_group(2, &sprite_bind_group); diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index c5dd8d389d6060..5cb8f9f0bff8da 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -12,6 +12,7 @@ use bevy_render::{ use bevy_sprite::{TextureAtlas, QUAD_HANDLE}; use bevy_text::{DefaultTextPipeline, DrawableText, Font, FontAtlasSet, TextError, TextStyle}; use bevy_transform::prelude::GlobalTransform; +use bevy_window::Windows; #[derive(Debug, Default)] pub struct QueuedText { @@ -27,13 +28,13 @@ pub struct Text { /// Defines how min_size, size, and max_size affects the bounds of a text /// block. -pub fn text_constraint(min_size: Val, size: Val, max_size: Val) -> f32 { +pub fn text_constraint(min_size: Val, size: Val, max_size: Val, scale_factor: f32) -> f32 { // Needs support for percentages match (min_size, size, max_size) { - (_, _, Val::Px(max)) => max, - (Val::Px(min), _, _) => min, - (Val::Undefined, Val::Px(size), Val::Undefined) => size, - (Val::Auto, Val::Px(size), Val::Auto) => size, + (_, _, Val::Px(max)) => max * scale_factor, + (Val::Px(min), _, _) => min * scale_factor, + (Val::Undefined, Val::Px(size), Val::Undefined) => size * scale_factor, + (Val::Auto, Val::Px(size), Val::Auto) => size * scale_factor, _ => f32::MAX, } } @@ -44,6 +45,7 @@ pub fn text_system( mut queued_text: Local, mut textures: ResMut>, fonts: Res>, + windows: Res, mut texture_atlases: ResMut>, mut font_atlas_set_storage: ResMut>, mut text_pipeline: ResMut, @@ -52,6 +54,12 @@ pub fn text_system( Query<(&Text, &Style, &mut CalculatedSize)>, )>, ) { + let scale_factor = if let Some(window) = windows.get_primary() { + window.scale_factor() as f32 + } else { + 1. + }; + // Adds all entities where the text or the style has changed to the local queue for entity in text_queries.q0_mut().iter_mut() { queued_text.entities.push(entity); @@ -70,6 +78,7 @@ pub fn text_system( entity, &*text, &*style, + scale_factor, &mut *textures, &*fonts, &mut *texture_atlases, @@ -80,7 +89,7 @@ pub fn text_system( let text_layout_info = text_pipeline.get_glyphs(&entity).expect( "Failed to get glyphs from the pipeline that have just been computed", ); - calculated_size.size = text_layout_info.size; + calculated_size.size = text_layout_info.size / scale_factor; } TextPipelineResult::Reschedule => { // There was an error processing the text layout, let's add this entity to the queue for further processing @@ -104,6 +113,7 @@ fn add_text_to_pipeline( entity: Entity, text: &Text, style: &Style, + scale_factor: f32, textures: &mut Assets, fonts: &Assets, texture_atlases: &mut Assets, @@ -111,11 +121,17 @@ fn add_text_to_pipeline( text_pipeline: &mut DefaultTextPipeline, ) -> TextPipelineResult { let node_size = Size::new( - text_constraint(style.min_size.width, style.size.width, style.max_size.width), + text_constraint( + style.min_size.width, + style.size.width, + style.max_size.width, + scale_factor, + ), text_constraint( style.min_size.height, style.size.height, style.max_size.height, + scale_factor, ), ); @@ -124,7 +140,7 @@ fn add_text_to_pipeline( text.font.clone(), &fonts, &text.value, - text.style.font_size, + text.style.font_size * scale_factor, text.style.alignment, node_size, font_atlas_set_storage, @@ -143,11 +159,18 @@ fn add_text_to_pipeline( pub fn draw_text_system( mut context: DrawContext, msaa: Res, + windows: Res, meshes: Res>, mut render_resource_bindings: ResMut, text_pipeline: Res, mut query: Query<(Entity, &mut Draw, &Visible, &Text, &Node, &GlobalTransform)>, ) { + let scale_factor = if let Some(window) = windows.get_primary() { + window.scale_factor() as f32 + } else { + 1. + }; + let font_quad = meshes.get(&QUAD_HANDLE).unwrap(); let vertex_buffer_descriptor = font_quad.get_vertex_buffer_descriptor(); @@ -162,6 +185,7 @@ pub fn draw_text_system( let mut drawable_text = DrawableText { render_resource_bindings: &mut render_resource_bindings, position, + inv_scale_factor: 1. / scale_factor, msaa: &msaa, text_glyphs: &text_glyphs.glyphs, font_quad_vertex_descriptor: &vertex_buffer_descriptor,