Skip to content

Commit

Permalink
Add Sprite Flipping
Browse files Browse the repository at this point in the history
  • Loading branch information
zicklag committed Feb 5, 2021
1 parent c87d4c1 commit 2400088
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 12 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ path = "examples/hello_world.rs"
name = "sprite"
path = "examples/2d/sprite.rs"

[[example]]
name = "sprite_flipping"
path = "examples/2d/sprite_flipping.rs"

[[example]]
name = "sprite_sheet"
path = "examples/2d/sprite_sheet.rs"
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_sprite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use texture_atlas_builder::*;
pub mod prelude {
pub use crate::{
entity::{SpriteBundle, SpriteSheetBundle},
ColorMaterial, Sprite, SpriteResizeMode, TextureAtlas, TextureAtlasSprite,
ColorMaterial, Sprite, SpriteFlip, SpriteResizeMode, TextureAtlas, TextureAtlasSprite,
};
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub fn build_sprite_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor
topology: PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: FrontFace::Ccw,
cull_mode: CullMode::None,
cull_mode: CullMode::Back,
polygon_mode: PolygonMode::Fill,
},
..PipelineDescriptor::new(ShaderStages {
Expand Down
18 changes: 17 additions & 1 deletion crates/bevy_sprite/src/render/sprite.vert
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,25 @@ layout(set = 2, binding = 0) uniform Transform {
layout(set = 2, binding = 1) uniform Sprite_size {
vec2 size;
};
layout(set = 2, binding = 2) uniform Sprite_flip {
uint flip;
};

void main() {
v_Uv = Vertex_Uv;
vec2 uv = Vertex_Uv;

// Flip the sprite if necessary
uint x_flip_bit = 1;
uint y_flip_bit = 2;
if ((flip & x_flip_bit) == x_flip_bit) {
uv = vec2(1.0 - uv.x , uv.y);
}
if ((flip & y_flip_bit) == y_flip_bit) {
uv = vec2(uv.x, 1.0 - uv.y);
}

v_Uv = uv;

vec3 position = Vertex_Position * vec3(size, 1.0);
gl_Position = ViewProj * Model * vec4(position, 1.0);
}
32 changes: 26 additions & 6 deletions crates/bevy_sprite/src/render/sprite_sheet.vert
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ layout(set = 2, binding = 0) uniform Transform {
mat4 SpriteTransform;
};

layout(set = 2, binding = 1) uniform TextureAtlasSprite {
vec4 TextureAtlasSprite_color;
uint TextureAtlasSprite_index;
layout(set = 2, binding = 1) uniform TextureAtlasSprite_color {
vec4 color;
};
layout(set = 2, binding = 2) uniform TextureAtlasSprite_index {
uint index;
};
layout(set = 2, binding = 3) uniform TextureAtlasSprite_flip {
uint flip;
};

void main() {
Rect sprite_rect = Textures[TextureAtlasSprite_index];
Rect sprite_rect = Textures[index];
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[](
Expand All @@ -45,7 +50,22 @@ void main() {
vec2(sprite_rect.end.x, sprite_rect.begin.y),
sprite_rect.end
);
v_Uv = (atlas_positions[gl_VertexIndex]) / AtlasSize;
v_Color = TextureAtlasSprite_color;

vec2 uv = (atlas_positions[gl_VertexIndex]) / AtlasSize;

// Flip the sprite if necessary
uint x_flip_bit = 1;
uint y_flip_bit = 2;

if ((flip & x_flip_bit) == x_flip_bit) {
uv = vec2(1.0 - uv.x , uv.y);
}
if ((flip & y_flip_bit) == y_flip_bit) {
uv = vec2(uv.x, 1.0 - uv.y);
}

v_Uv = uv;

v_Color = color;
gl_Position = ViewProj * SpriteTransform * vec4(vertex_position, 1.0);
}
34 changes: 33 additions & 1 deletion crates/bevy_sprite/src/sprite.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
use crate::ColorMaterial;
use bevy_asset::{Assets, Handle};
use bevy_core::Bytes;
use bevy_ecs::{Query, Res};
use bevy_math::Vec2;
use bevy_reflect::{Reflect, ReflectDeserialize, TypeUuid};
use bevy_render::{renderer::RenderResources, texture::Texture};
use bevy_render::{
renderer::{RenderResource, RenderResourceType, RenderResources},
texture::Texture,
};
use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Clone, RenderResources, TypeUuid, Reflect)]
#[uuid = "7233c597-ccfa-411f-bd59-9af349432ada"]
pub struct Sprite {
pub size: Vec2,
pub flip: SpriteFlip,
#[render_resources(ignore)]
pub resize_mode: SpriteResizeMode,
}

/// Indicates how to flip the sprite
#[derive(Default, Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
pub struct SpriteFlip {
pub x: bool,
pub y: bool,
}

impl RenderResource for SpriteFlip {
fn resource_type(&self) -> Option<RenderResourceType> {
Some(RenderResourceType::Buffer)
}

fn write_buffer_bytes(&self, buffer: &mut [u8]) {
// First bit means flip x, second bit means flip y
(if self.x { 0b01 } else { 0 } | if self.y { 0b10 } else { 0 } as u32).write_bytes(buffer);
}

fn buffer_byte_len(&self) -> Option<usize> {
Some(4)
}

fn texture(&self) -> Option<&Handle<Texture>> {
None
}
}

/// Determines how `Sprite` resize should be handled
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect_value(PartialEq, Serialize, Deserialize)]
Expand All @@ -34,6 +65,7 @@ impl Sprite {
Self {
size,
resize_mode: SpriteResizeMode::Manual,
flip: SpriteFlip::default(),
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_sprite/src/texture_atlas.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Rect;
use crate::{Rect, SpriteFlip};
use bevy_asset::Handle;
use bevy_core::Byteable;
use bevy_math::Vec2;
Expand Down Expand Up @@ -26,17 +26,18 @@ pub struct TextureAtlas {
}

#[derive(Debug, RenderResources, RenderResource, Clone)]
#[render_resources(from_self)]
pub struct TextureAtlasSprite {
pub color: Color,
pub index: u32,
pub flip: SpriteFlip,
}

impl Default for TextureAtlasSprite {
fn default() -> Self {
Self {
index: 0,
color: Color::WHITE,
flip: Default::default(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_text/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ impl<'a> Drawable for DrawableText<'a> {
let sprite = TextureAtlasSprite {
index: tv.atlas_info.glyph_index,
color: self.sections[tv.section_index].style.color,
flip: Default::default(),
};

// To get the rendering right for non-one scaling factors, we need
Expand Down
1 change: 1 addition & 0 deletions examples/2d/contributors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ fn setup(
sprite: Sprite {
size: Vec2::new(1.0, 1.0) * SPRITE_SIZE,
resize_mode: SpriteResizeMode::Manual,
..Default::default()
},
material: materials.add(ColorMaterial {
color: COL_DESELECTED * col,
Expand Down
27 changes: 27 additions & 0 deletions examples/2d/sprite_flipping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use bevy::prelude::*;

fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.run();
}

fn setup(
commands: &mut Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let texture_handle = asset_server.load("branding/icon.png");
commands
.spawn(OrthographicCameraBundle::new_2d())
.spawn(SpriteBundle {
material: materials.add(texture_handle.into()),
sprite: Sprite {
// Flip the logo to the left
flip: SpriteFlip { x: true, y: false },
..Default::default()
},
..Default::default()
});
}

0 comments on commit 2400088

Please sign in to comment.