From cfbff734dacb6beb6b0aead8c06bee5318698b1c Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Tue, 29 Dec 2020 07:05:34 -0800 Subject: [PATCH] rework high DPI text rendering to not change sprite sheet shader --- crates/bevy_sprite/src/entity.rs | 4 +-- crates/bevy_sprite/src/render/mod.rs | 8 +---- .../bevy_sprite/src/render/sprite_sheet.vert | 6 +--- crates/bevy_text/src/draw.rs | 20 +++++++++--- crates/bevy_text/src/text2d.rs | 2 +- crates/bevy_ui/src/widget/text.rs | 31 +++++++++++++------ 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/crates/bevy_sprite/src/entity.rs b/crates/bevy_sprite/src/entity.rs index 6f278323273ab..9136cce5ed598 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, TextureAtlasSpriteScale, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE, + TextureAtlasSprite, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE, }; use bevy_asset::Handle; use bevy_ecs::Bundle; @@ -52,7 +52,6 @@ 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 @@ -79,7 +78,6 @@ 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 570e6faa7425e..221df7cb95091 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, TextureAtlasSpriteScale}; +use crate::{ColorMaterial, Sprite, TextureAtlas, TextureAtlasSprite}; use bevy_asset::{Assets, HandleUntyped}; use bevy_ecs::Resources; use bevy_reflect::TypeUuid; @@ -119,7 +119,6 @@ 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"; } @@ -150,11 +149,6 @@ 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 c9fff68f49197..d967ac5411ba3 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -35,13 +35,9 @@ 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)*SpriteScale; + vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin; 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_text/src/draw.rs b/crates/bevy_text/src/draw.rs index a216dfffdce6a..a04e60b28c68c 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -48,7 +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 scale_factor: f32, pub style: &'a TextStyle, pub text_glyphs: &'a Vec, pub msaa: &'a Msaa, @@ -98,7 +98,7 @@ 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); + let scale = Vec2::splat(1.); for tv in self.text_glyphs { context.set_asset_bind_groups(draw, &tv.atlas_info.texture_atlas)?; @@ -108,8 +108,20 @@ impl<'a> Drawable for DrawableText<'a> { color: self.style.color, }; - let transform = Mat4::from_translation( - self.position + (tv.position * self.inv_scale_factor).extend(0.), + // To get the rendering right for non-one scaling factors, we need + // the sprite to be drawn in "physical" coordinates. This is because + // the shader uses the size of the sprite to control the size on + // screen. To accomplish this we make the sprite transform + // convert from physical coordinates to logical coordinates in + // addition to altering the origin. Since individual glyphs will + // already be in physical coordinates, we just need to convert the + // overall position to physical coordinates to get the sprites + // physical position. + + let transform = Mat4::from_scale( + Vec3::splat(1./self.scale_factor) + )*Mat4::from_translation( + self.position*self.scale_factor + tv.position.extend(0.), ); let transform_buffer = context.get_uniform_buffer(&transform).unwrap(); diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 3048c401a4844..48cf328106b72 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -105,7 +105,7 @@ pub fn draw_text2d_system( msaa: &msaa, text_glyphs: &text_glyphs.glyphs, font_quad_vertex_descriptor: &vertex_buffer_descriptor, - inv_scale_factor: 1., + scale_factor: 1., style: &text.style, }; diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index 9856d8552290a..5271ffda93b75 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -21,15 +21,21 @@ pub struct QueuedText { entities: Vec, } +fn scale_value(value: f32, factor: f64) -> f32 { + let result = ((value as f64) * factor) as f32; + println!("scale: {}*{} -> {}", value, factor, result); + result +} + /// 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, scale_factor: f32) -> f32 { +pub fn text_constraint(min_size: Val, size: Val, max_size: Val, scale_factor: f64) -> f32 { // Needs support for percentages match (min_size, size, max_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, + (_, _, Val::Px(max)) => scale_value(max, scale_factor), + (Val::Px(min), _, _) => scale_value(min, scale_factor), + (Val::Undefined, Val::Px(size), Val::Undefined) => scale_value(size, scale_factor), + (Val::Auto, Val::Px(size), Val::Auto) => scale_value(size, scale_factor), _ => f32::MAX, } } @@ -51,11 +57,13 @@ pub fn text_system( )>, ) { let scale_factor = if let Some(window) = windows.get_primary() { - window.scale_factor() as f32 + window.scale_factor() } else { 1. }; + let inv_scale_factor = 1. / scale_factor; + // 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); @@ -90,7 +98,7 @@ pub fn text_system( text.font.clone(), &fonts, &text.value, - text.style.font_size, + scale_value(text.style.font_size, scale_factor), text.style.alignment, node_size, &mut *font_atlas_set_storage, @@ -108,7 +116,10 @@ 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 / scale_factor; + calculated_size.size = Size{ + width: scale_value(text_layout_info.size.width, inv_scale_factor), + height: scale_value(text_layout_info.size.height, inv_scale_factor), + }; } } } @@ -128,7 +139,7 @@ pub fn draw_text_system( 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 + window.scale_factor() } else { 1. }; @@ -147,7 +158,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, + scale_factor: scale_factor as f32, msaa: &msaa, text_glyphs: &text_glyphs.glyphs, font_quad_vertex_descriptor: &vertex_buffer_descriptor,