mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
sprite: add color to TextureAtlasSprite and make Vec3 16 bytes again to account for glsl UBO layout
This commit is contained in:
parent
17d70f7d67
commit
faacd2778d
13 changed files with 81 additions and 65 deletions
|
@ -91,58 +91,11 @@ unsafe impl Byteable for i64 {}
|
|||
unsafe impl Byteable for isize {}
|
||||
unsafe impl Byteable for f32 {}
|
||||
unsafe impl Byteable for f64 {}
|
||||
|
||||
impl Bytes for Vec2 {
|
||||
fn write_bytes(&self, buffer: &mut [u8]) {
|
||||
let array: [f32; 2] = (*self).into();
|
||||
array.write_bytes(buffer);
|
||||
}
|
||||
fn byte_len(&self) -> usize {
|
||||
std::mem::size_of::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBytes for Vec2 {
|
||||
fn from_bytes(bytes: &[u8]) -> Self {
|
||||
let array = <[f32; 2]>::from_bytes(bytes);
|
||||
Vec2::from(array)
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes for Vec3 {
|
||||
fn write_bytes(&self, buffer: &mut [u8]) {
|
||||
let array: [f32; 3] = (*self).into();
|
||||
array.write_bytes(buffer);
|
||||
}
|
||||
fn byte_len(&self) -> usize {
|
||||
// cant use self here because Vec3 is a simd type / technically a vec4
|
||||
std::mem::size_of::<[f32; 3]>()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBytes for Vec3 {
|
||||
fn from_bytes(bytes: &[u8]) -> Self {
|
||||
let array = <[f32; 3]>::from_bytes(bytes);
|
||||
Vec3::from(array)
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes for Vec4 {
|
||||
fn write_bytes(&self, buffer: &mut [u8]) {
|
||||
let array: [f32; 4] = (*self).into();
|
||||
array.write_bytes(buffer);
|
||||
}
|
||||
fn byte_len(&self) -> usize {
|
||||
std::mem::size_of::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBytes for Vec4 {
|
||||
fn from_bytes(bytes: &[u8]) -> Self {
|
||||
let array = <[f32; 4]>::from_bytes(bytes);
|
||||
Vec4::from(array)
|
||||
}
|
||||
}
|
||||
unsafe impl Byteable for Vec2 {}
|
||||
// NOTE: Vec3 actually takes up the size of 4 floats / 16 bytes due to SIMD. This is actually convenient because GLSL
|
||||
// uniform buffer objects pad Vec3s to be 16 bytes.
|
||||
unsafe impl Byteable for Vec3 {}
|
||||
unsafe impl Byteable for Vec4 {}
|
||||
|
||||
impl Bytes for Mat4 {
|
||||
fn write_bytes(&self, buffer: &mut [u8]) {
|
||||
|
|
|
@ -25,7 +25,7 @@ impl AppPlugin for PbrPlugin {
|
|||
.register_component::<Light>()
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
shader::asset_shader_def_system::<StandardMaterial>.system(),
|
||||
shader::asset_shader_defs_system::<StandardMaterial>.system(),
|
||||
);
|
||||
let resources = app.resources();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
|
|
|
@ -219,6 +219,7 @@ impl<'a> DrawContext<'a> {
|
|||
specialization,
|
||||
)
|
||||
};
|
||||
|
||||
draw.set_pipeline(specialized_pipeline);
|
||||
self.current_pipeline = Some(specialized_pipeline);
|
||||
Ok(())
|
||||
|
|
|
@ -41,6 +41,7 @@ use mesh::mesh_resource_provider_system;
|
|||
use pipeline::{draw_render_pipelines_system, RenderPipelines};
|
||||
use render_graph::{system::render_graph_schedule_executor_system, RenderGraph};
|
||||
use render_resource::AssetRenderResourceBindings;
|
||||
use shader::clear_shader_defs_system;
|
||||
use std::ops::Range;
|
||||
use texture::{PngTextureLoader, TextureResourceSystemState};
|
||||
|
||||
|
@ -112,7 +113,8 @@ impl AppPlugin for RenderPlugin {
|
|||
stage::RENDER_GRAPH_SYSTEMS,
|
||||
render_graph_schedule_executor_system,
|
||||
)
|
||||
.add_system_to_stage(stage::DRAW, draw_render_pipelines_system.system());
|
||||
.add_system_to_stage(stage::DRAW, draw_render_pipelines_system.system())
|
||||
.add_system_to_stage(stage::POST_RENDER, clear_shader_defs_system.system());
|
||||
|
||||
if let Some(ref config) = self.base_render_graph_config {
|
||||
let resources = app.resources();
|
||||
|
|
|
@ -14,7 +14,7 @@ impl PipelineLayout {
|
|||
.iter()
|
||||
.find(|bind_group| bind_group.index == index)
|
||||
}
|
||||
|
||||
|
||||
pub fn from_shader_layouts(shader_layouts: &mut [ShaderLayout]) -> Self {
|
||||
let mut bind_groups = HashMap::<u32, BindGroupDescriptor>::new();
|
||||
let mut vertex_buffer_descriptors = Vec::new();
|
||||
|
|
|
@ -55,7 +55,7 @@ impl ShaderDef for Option<Handle<Texture>> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn shader_def_system<T>(shader_defs: Com<T>, mut render_pipelines: ComMut<RenderPipelines>)
|
||||
pub fn shader_defs_system<T>(shader_defs: Com<T>, mut render_pipelines: ComMut<RenderPipelines>)
|
||||
where
|
||||
T: ShaderDefs + Send + Sync + 'static,
|
||||
{
|
||||
|
@ -70,7 +70,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn asset_shader_def_system<T>(
|
||||
pub fn clear_shader_defs_system(mut render_pipelines: ComMut<RenderPipelines>) {
|
||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||
render_pipeline
|
||||
.specialization
|
||||
.shader_specialization
|
||||
.shader_defs
|
||||
.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn asset_shader_defs_system<T>(
|
||||
assets: Res<Assets<T>>,
|
||||
asset_handle: Com<Handle<T>>,
|
||||
mut render_pipelines: ComMut<RenderPipelines>,
|
||||
|
|
|
@ -22,7 +22,7 @@ use bevy_asset::{AddAsset, Assets, Handle};
|
|||
use bevy_render::{
|
||||
mesh::{shape, Mesh},
|
||||
render_graph::RenderGraph,
|
||||
shader::asset_shader_def_system,
|
||||
shader::asset_shader_defs_system,
|
||||
};
|
||||
use glam::Vec2;
|
||||
use legion::prelude::IntoSystem;
|
||||
|
@ -40,7 +40,7 @@ impl AppPlugin for SpritePlugin {
|
|||
.add_system_to_stage(stage::POST_UPDATE, sprite_system())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
asset_shader_def_system::<ColorMaterial>.system(),
|
||||
asset_shader_defs_system::<ColorMaterial>.system(),
|
||||
);
|
||||
|
||||
let resources = app.resources();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 v_Uv;
|
||||
layout(location = 1) in vec4 v_Color;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
|
@ -8,7 +9,7 @@ layout(set = 1, binding = 2) uniform texture2D TextureAtlas_texture;
|
|||
layout(set = 1, binding = 3) uniform sampler TextureAtlas_texture_sampler;
|
||||
|
||||
void main() {
|
||||
o_Target = texture(
|
||||
o_Target = v_Color * texture(
|
||||
sampler2D(TextureAtlas_texture, TextureAtlas_texture_sampler),
|
||||
v_Uv);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ layout(location = 1) in vec3 Vertex_Normal;
|
|||
layout(location = 2) in vec2 Vertex_Uv;
|
||||
|
||||
layout(location = 0) out vec2 v_Uv;
|
||||
layout(location = 1) out vec4 v_Color;
|
||||
|
||||
// TODO: remove UI shader def and replace with generic "Camera" when its easier to manually bind global RenderResourceBindings
|
||||
#ifdef UI_CAMERA
|
||||
|
@ -34,6 +35,7 @@ layout(set = 1, binding = 1) buffer TextureAtlas_textures {
|
|||
|
||||
layout(set = 2, binding = 0) uniform TextureAtlasSprite {
|
||||
vec3 TextureAtlasSprite_position;
|
||||
vec4 TextureAtlasSprite_color;
|
||||
float TextureAtlasSprite_scale;
|
||||
uint TextureAtlasSprite_index;
|
||||
};
|
||||
|
@ -41,7 +43,7 @@ layout(set = 2, binding = 0) uniform TextureAtlasSprite {
|
|||
void main() {
|
||||
Rect sprite_rect = Textures[TextureAtlasSprite_index];
|
||||
vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin;
|
||||
vec3 vertex_position = vec3(Vertex_Position.xy * sprite_dimensions * TextureAtlasSprite_scale, 0.0) + TextureAtlasSprite_position;
|
||||
vec3 vertex_position = vec3(Vertex_Position.xy * sprite_dimensions * TextureAtlasSprite_scale, 0.0) + TextureAtlasSprite_position.xyz;
|
||||
vec2 uvs[4] = vec2[](
|
||||
vec2(sprite_rect.begin.x, sprite_rect.end.y),
|
||||
sprite_rect.begin,
|
||||
|
@ -49,5 +51,6 @@ void main() {
|
|||
sprite_rect.end
|
||||
);
|
||||
v_Uv = uvs[gl_VertexIndex] / AtlasSize;
|
||||
v_Color = TextureAtlasSprite_color;
|
||||
gl_Position = ViewProj * vec4(vertex_position, 1.0);
|
||||
}
|
|
@ -4,6 +4,7 @@ use bevy_core::bytes::Bytes;
|
|||
use bevy_render::{
|
||||
render_resource::{RenderResource, RenderResources},
|
||||
texture::Texture,
|
||||
Color,
|
||||
};
|
||||
use glam::{Vec2, Vec3};
|
||||
use std::collections::HashMap;
|
||||
|
@ -21,14 +22,26 @@ pub struct TextureAtlas {
|
|||
|
||||
// NOTE: cannot do `unsafe impl Byteable` here because Vec3 takes up the space of a Vec4. If/when glam changes this we can swap out
|
||||
// Bytes for Byteable as a micro-optimization. https://github.com/bitshifter/glam-rs/issues/36
|
||||
#[derive(Bytes, RenderResources, RenderResource, Default)]
|
||||
#[derive(Bytes, RenderResources, RenderResource)]
|
||||
#[render_resources(from_self)]
|
||||
pub struct TextureAtlasSprite {
|
||||
pub position: Vec3,
|
||||
pub color: Color,
|
||||
pub scale: f32,
|
||||
pub index: u32,
|
||||
}
|
||||
|
||||
impl Default for TextureAtlasSprite {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
index: 0,
|
||||
color: Color::WHITE,
|
||||
scale: 1.0,
|
||||
position: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TextureAtlas {
|
||||
pub fn new_empty(texture: Handle<Texture>, dimensions: Vec2) -> Self {
|
||||
Self {
|
||||
|
@ -81,3 +94,36 @@ impl TextureAtlas {
|
|||
.and_then(|texture_handles| texture_handles.get(&texture).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::TextureAtlasSprite;
|
||||
use bevy_core::bytes::{Bytes, FromBytes};
|
||||
use bevy_render::Color;
|
||||
use glam::Vec3;
|
||||
|
||||
#[test]
|
||||
fn test_atlas_byte_conversion() {
|
||||
let x = TextureAtlasSprite {
|
||||
color: Color::RED,
|
||||
index: 2,
|
||||
position: Vec3::new(1., 2., 3.),
|
||||
scale: 4.0,
|
||||
};
|
||||
|
||||
assert_eq!(x.byte_len(), 36);
|
||||
let mut bytes = vec![0; x.byte_len()];
|
||||
|
||||
x.write_bytes(&mut bytes);
|
||||
|
||||
let position = Vec3::from_bytes(&bytes[0..12]);
|
||||
let color = Color::from_bytes(&bytes[12..28]);
|
||||
let scale = f32::from_bytes(&bytes[28..32]);
|
||||
let index = u32::from_bytes(&bytes[32..36]);
|
||||
|
||||
assert_eq!(position, x.position);
|
||||
assert_eq!(color, x.color);
|
||||
assert_eq!(scale, x.scale);
|
||||
assert_eq!(index, x.index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ impl<'a> Drawable for DrawableText<'a> {
|
|||
let offset = scaled_font.descent() + glyph_height;
|
||||
let sprite_buffer = TextureAtlasSprite {
|
||||
index: glyph_atlas_info.char_index,
|
||||
color: self.style.color,
|
||||
position: caret
|
||||
+ Vec3::new(
|
||||
0.0 + glyph_width / 2.0 + bounds.min.x,
|
||||
|
|
|
@ -42,9 +42,8 @@ fn setup(
|
|||
.add_entity(SpriteSheetEntity {
|
||||
texture_atlas: texture_atlas_handle,
|
||||
sprite: TextureAtlasSprite {
|
||||
index: 0,
|
||||
scale: 6.0,
|
||||
position: Vec3::new(0.0, 0.0, 0.0),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
|||
.add_startup_system(setup.system())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
shader::asset_shader_def_system::<MyMaterial>.system(),
|
||||
shader::asset_shader_defs_system::<MyMaterial>.system(),
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue