From 5b86b2d9f5fe8b2e2fe03cb3c56313275f16a825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 19:15:45 +0100 Subject: [PATCH 1/7] extracted sprites use a 2d transform separated from its z level --- crates/bevy_sprite/src/render/mod.rs | 53 +++++++++++++++++++--------- crates/bevy_text/src/text2d.rs | 9 +++-- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 7e3ffe4c97038..ce8ff222ac985 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -11,7 +11,7 @@ use bevy_ecs::{ prelude::*, system::{lifetimeless::*, SystemParamItem}, }; -use bevy_math::{const_vec2, Vec2}; +use bevy_math::{const_vec2, Quat, Vec2}; use bevy_reflect::Uuid; use bevy_render::{ color::Color, @@ -173,7 +173,8 @@ impl SpecializedPipeline for SpritePipeline { #[derive(Component, Clone, Copy)] pub struct ExtractedSprite { - pub transform: GlobalTransform, + pub transform: Transform2d, + pub z_layer: f32, pub color: Color, /// Select an area of the texture pub rect: Option, @@ -186,6 +187,22 @@ pub struct ExtractedSprite { pub flip_y: bool, } +#[derive(Clone, Copy)] +pub struct Transform2d { + pub translation: Vec2, + pub scale: Vec2, + pub rotation: Quat, +} + +impl Transform2d { + fn mul_vec2(&self, mut value: Vec2) -> Vec2 { + value = self.scale * value; + value = (self.rotation * value.extend(0.0)).truncate(); + value += self.translation; + value + } +} + #[derive(Default)] pub struct ExtractedSprites { pub sprites: Vec, @@ -240,7 +257,12 @@ pub fn extract_sprites( // PERF: we don't check in this function that the `Image` asset is ready, since it should be in most cases and hashing the handle is expensive extracted_sprites.sprites.alloc().init(ExtractedSprite { color: sprite.color, - transform: *transform, + transform: Transform2d { + translation: transform.translation.truncate(), + scale: transform.scale.truncate(), + rotation: transform.rotation, + }, + z_layer: transform.translation.z * transform.scale.z, // Use the full texture rect: None, // Pass the custom size @@ -258,7 +280,12 @@ pub fn extract_sprites( let rect = Some(texture_atlas.textures[atlas_sprite.index as usize]); extracted_sprites.sprites.alloc().init(ExtractedSprite { color: atlas_sprite.color, - transform: *transform, + transform: Transform2d { + translation: transform.translation.truncate(), + scale: transform.scale.truncate(), + rotation: transform.rotation, + }, + z_layer: transform.translation.z * transform.scale.z, // Select the area in the texture atlas rect, // Pass the custom size @@ -393,16 +420,9 @@ pub fn queue_sprites( 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, - } + extracted_sprites.sort_unstable_by(|a, b| match a.z_layer.partial_cmp(&b.z_layer) { + 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 @@ -489,12 +509,13 @@ pub fn queue_sprites( let positions = QUAD_VERTEX_POSITIONS.map(|quad_pos| { extracted_sprite .transform - .mul_vec3((quad_pos * quad_size).extend(0.)) + .mul_vec2(quad_pos * quad_size) + .extend(extracted_sprite.z_layer) .into() }); // These items will be sorted by depth with other phase items - let sort_key = FloatOrd(extracted_sprite.transform.translation.z); + let sort_key = FloatOrd(extracted_sprite.z_layer); // Store the vertex data and add the item to the render phase if current_batch.colored { diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 0119bffde7b6e..eb3b95749453c 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -7,7 +7,7 @@ use bevy_ecs::{ }; use bevy_math::{Size, Vec3}; use bevy_render::{texture::Image, view::Visibility, RenderWorld}; -use bevy_sprite::{ExtractedSprite, ExtractedSprites, TextureAtlas}; +use bevy_sprite::{ExtractedSprite, ExtractedSprites, TextureAtlas, Transform2d}; use bevy_transform::prelude::{GlobalTransform, Transform}; use bevy_window::{WindowId, Windows}; @@ -92,7 +92,12 @@ pub fn extract_text2d_sprite( let transform = text_transform.mul_transform(glyph_transform); extracted_sprites.sprites.push(ExtractedSprite { - transform, + transform: Transform2d { + translation: transform.translation.truncate(), + scale: transform.scale.truncate(), + rotation: transform.rotation, + }, + z_layer: transform.translation.z * transform.scale.z, color, rect, custom_size: None, From c182854e88cad5d44e2d1eb8a0363f6fc2e0f86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 20:24:25 +0100 Subject: [PATCH 2/7] simplify mul operation --- crates/bevy_sprite/src/render/mod.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index ce8ff222ac985..00bb4093e766a 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -195,11 +195,8 @@ pub struct Transform2d { } impl Transform2d { - fn mul_vec2(&self, mut value: Vec2) -> Vec2 { - value = self.scale * value; - value = (self.rotation * value.extend(0.0)).truncate(); - value += self.translation; - value + fn mul_vec2(&self, value: Vec2) -> Vec2 { + (self.rotation * (self.scale * value).extend(0.0)).truncate() + self.translation } } From e153172e798193e18f63d75d2b424253eec3701e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 20:25:34 +0100 Subject: [PATCH 3/7] inline it --- crates/bevy_sprite/src/render/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 00bb4093e766a..8d149cea33c94 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -195,6 +195,7 @@ pub struct Transform2d { } impl Transform2d { + #[inline] fn mul_vec2(&self, value: Vec2) -> Vec2 { (self.rotation * (self.scale * value).extend(0.0)).truncate() + self.translation } From 4492d3f445b6ed31efee21356e02698d276a3e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 21:19:35 +0100 Subject: [PATCH 4/7] single line for `mul_vec3` --- crates/bevy_transform/src/components/global_transform.rs | 7 ++----- crates/bevy_transform/src/components/transform.rs | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index 68664507d4455..864a711213baf 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -212,11 +212,8 @@ impl GlobalTransform { /// Returns a [`Vec3`] of this [`Transform`] applied to `value`. #[inline] - pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 { - value = self.scale * value; - value = self.rotation * value; - value += self.translation; - value + pub fn mul_vec3(&self, value: Vec3) -> Vec3 { + self.rotation * self.scale * value + self.translation } #[doc(hidden)] diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index f0c6d536f3982..b691e55524548 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -222,11 +222,8 @@ impl Transform { /// Returns a [`Vec3`] of this [`Transform`] applied to `value`. #[inline] - pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 { - value = self.scale * value; - value = self.rotation * value; - value += self.translation; - value + pub fn mul_vec3(&self, value: Vec3) -> Vec3 { + self.rotation * self.scale * value + self.translation } /// Changes the `scale` of this [`Transform`], multiplying the current `scale` by From de07ac3998cceeb25c1289c6c4bfb205c8bceea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 21:45:16 +0100 Subject: [PATCH 5/7] keep the order --- crates/bevy_transform/src/components/global_transform.rs | 2 +- crates/bevy_transform/src/components/transform.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index 864a711213baf..454727e56fcc6 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -213,7 +213,7 @@ impl GlobalTransform { /// Returns a [`Vec3`] of this [`Transform`] applied to `value`. #[inline] pub fn mul_vec3(&self, value: Vec3) -> Vec3 { - self.rotation * self.scale * value + self.translation + self.rotation * (self.scale * value) + self.translation } #[doc(hidden)] diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index b691e55524548..dbfda73948872 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -223,7 +223,7 @@ impl Transform { /// Returns a [`Vec3`] of this [`Transform`] applied to `value`. #[inline] pub fn mul_vec3(&self, value: Vec3) -> Vec3 { - self.rotation * self.scale * value + self.translation + self.rotation * (self.scale * value) + self.translation } /// Changes the `scale` of this [`Transform`], multiplying the current `scale` by From 060d6445685fea053bb67a30044a6c56e0ede028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 21:55:40 +0100 Subject: [PATCH 6/7] doc strings --- crates/bevy_sprite/src/render/mod.rs | 20 +++++++++++++++----- crates/bevy_text/src/text2d.rs | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 8d149cea33c94..89a87490f908c 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -171,10 +171,14 @@ impl SpecializedPipeline for SpritePipeline { } } +/// Extracted informations about a [`Sprite`] used to render it. #[derive(Component, Clone, Copy)] pub struct ExtractedSprite { - pub transform: Transform2d, + /// 2d extracted transform from the sprite [`bevy_transform::GlobalTransform`] + pub transform: Extracted2dTransform, + /// Z layer at which the sprite should be shown pub z_layer: f32, + /// Color of the sprite pub color: Color, /// Select an area of the texture pub rect: Option, @@ -183,18 +187,24 @@ pub struct ExtractedSprite { /// Handle to the `Image` of this sprite /// PERF: storing a `HandleId` instead of `Handle` enables some optimizations (`ExtractedSprite` becomes `Copy` and doesn't need to be dropped) pub image_handle_id: HandleId, + /// Is it flipped along the X axis pub flip_x: bool, + /// Is it flipped along the Y axis pub flip_y: bool, } +/// A 2d representation of a [`bevy_transform::GlobalTransform`] for an [`ExtractedSprite`] #[derive(Clone, Copy)] -pub struct Transform2d { +pub struct Extracted2dTransform { + /// The 2d position pub translation: Vec2, + /// The 2d scale pub scale: Vec2, + /// The rotation pub rotation: Quat, } -impl Transform2d { +impl Extracted2dTransform { #[inline] fn mul_vec2(&self, value: Vec2) -> Vec2 { (self.rotation * (self.scale * value).extend(0.0)).truncate() + self.translation @@ -255,7 +265,7 @@ pub fn extract_sprites( // PERF: we don't check in this function that the `Image` asset is ready, since it should be in most cases and hashing the handle is expensive extracted_sprites.sprites.alloc().init(ExtractedSprite { color: sprite.color, - transform: Transform2d { + transform: Extracted2dTransform { translation: transform.translation.truncate(), scale: transform.scale.truncate(), rotation: transform.rotation, @@ -278,7 +288,7 @@ pub fn extract_sprites( let rect = Some(texture_atlas.textures[atlas_sprite.index as usize]); extracted_sprites.sprites.alloc().init(ExtractedSprite { color: atlas_sprite.color, - transform: Transform2d { + transform: Extracted2dTransform { translation: transform.translation.truncate(), scale: transform.scale.truncate(), rotation: transform.rotation, diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index eb3b95749453c..6f84784881dbd 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -7,7 +7,7 @@ use bevy_ecs::{ }; use bevy_math::{Size, Vec3}; use bevy_render::{texture::Image, view::Visibility, RenderWorld}; -use bevy_sprite::{ExtractedSprite, ExtractedSprites, TextureAtlas, Transform2d}; +use bevy_sprite::{Extracted2dTransform, ExtractedSprite, ExtractedSprites, TextureAtlas}; use bevy_transform::prelude::{GlobalTransform, Transform}; use bevy_window::{WindowId, Windows}; @@ -92,7 +92,7 @@ pub fn extract_text2d_sprite( let transform = text_transform.mul_transform(glyph_transform); extracted_sprites.sprites.push(ExtractedSprite { - transform: Transform2d { + transform: Extracted2dTransform { translation: transform.translation.truncate(), scale: transform.scale.truncate(), rotation: transform.rotation, From 08034fe1d0e6db19214a7ad861ef885ce48967be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 8 Mar 2022 22:20:04 +0100 Subject: [PATCH 7/7] fix doc links --- crates/bevy_sprite/src/render/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 89a87490f908c..154d2eb1b7d57 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -174,7 +174,7 @@ impl SpecializedPipeline for SpritePipeline { /// Extracted informations about a [`Sprite`] used to render it. #[derive(Component, Clone, Copy)] pub struct ExtractedSprite { - /// 2d extracted transform from the sprite [`bevy_transform::GlobalTransform`] + /// 2d extracted transform from the sprite [`GlobalTransform`] pub transform: Extracted2dTransform, /// Z layer at which the sprite should be shown pub z_layer: f32, @@ -193,7 +193,7 @@ pub struct ExtractedSprite { pub flip_y: bool, } -/// A 2d representation of a [`bevy_transform::GlobalTransform`] for an [`ExtractedSprite`] +/// A 2d representation of a [`GlobalTransform`] for an [`ExtractedSprite`] #[derive(Clone, Copy)] pub struct Extracted2dTransform { /// The 2d position