Skip to content

Commit

Permalink
render UI text at physical resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
blunted2night committed Dec 22, 2020
1 parent 02aa17c commit 86b3e90
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 13 deletions.
4 changes: 3 additions & 1 deletion crates/bevy_sprite/src/entity.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<TextureAtlas>,
/// Data pertaining to how the sprite is drawn on the screen
Expand All @@ -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(),
Expand Down
8 changes: 7 additions & 1 deletion crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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";
}

Expand Down Expand Up @@ -149,6 +150,11 @@ impl SpriteRenderGraphBuilder for RenderGraph {
RenderResourcesNode::<TextureAtlasSprite>::new(true),
);

self.add_system_node(
node::SPRITE_SHEET_SCALE,
RenderResourcesNode::<TextureAtlasSpriteScale>::new(true),
);

let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
pipelines.set_untracked(SPRITE_PIPELINE_HANDLE, build_sprite_pipeline(&mut shaders));
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_sprite/src/render/sprite_sheet.vert
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
22 changes: 22 additions & 0 deletions crates/bevy_sprite/src/texture_atlas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 9 additions & 2 deletions crates/bevy_text/src/draw.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -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<PositionedGlyph>,
pub msaa: &'a Msaa,
Expand Down Expand Up @@ -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)?;

Expand All @@ -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);
Expand Down
41 changes: 33 additions & 8 deletions crates/bevy_ui/src/widget/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -27,23 +28,25 @@ 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,
}
}

/// Computes the size of a text block and updates the TextGlyphs with the
/// new computed glyphs from the layout
#[allow(clippy::too_many_arguments)]
pub fn text_system(
mut queued_text: Local<QueuedText>,
mut textures: ResMut<Assets<Texture>>,
fonts: Res<Assets<Font>>,
windows: Res<Windows>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,
mut text_pipeline: ResMut<DefaultTextPipeline>,
Expand All @@ -52,6 +55,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);
Expand All @@ -70,6 +79,7 @@ pub fn text_system(
entity,
&*text,
&*style,
scale_factor,
&mut *textures,
&*fonts,
&mut *texture_atlases,
Expand All @@ -80,7 +90,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
Expand All @@ -104,18 +114,25 @@ fn add_text_to_pipeline(
entity: Entity,
text: &Text,
style: &Style,
scale_factor: f32,
textures: &mut Assets<Texture>,
fonts: &Assets<Font>,
texture_atlases: &mut Assets<TextureAtlas>,
font_atlas_set_storage: &mut Assets<FontAtlasSet>,
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,
),
);

Expand All @@ -124,7 +141,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,
Expand All @@ -143,11 +160,18 @@ fn add_text_to_pipeline(
pub fn draw_text_system(
mut context: DrawContext,
msaa: Res<Msaa>,
windows: Res<Windows>,
meshes: Res<Assets<Mesh>>,
mut render_resource_bindings: ResMut<RenderResourceBindings>,
text_pipeline: Res<DefaultTextPipeline>,
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();

Expand All @@ -162,6 +186,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,
Expand Down

0 comments on commit 86b3e90

Please sign in to comment.