From 1056b79abf648a2304137fbb194e31e586332a45 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sun, 3 May 2020 23:49:45 -0700 Subject: [PATCH] ui textures --- crates/bevy_ui/src/color_material.rs | 55 ++++++++++++++++++++++ crates/bevy_ui/src/entity.rs | 16 +++---- crates/bevy_ui/src/lib.rs | 41 ++++++++++++----- crates/bevy_ui/src/rect.rs | 2 - crates/bevy_ui/src/render/mod.rs | 6 ++- crates/bevy_ui/src/render/ui.frag | 19 +++++++- crates/bevy_ui/src/render/ui.vert | 5 +- examples/ui/ui.rs | 68 +++++++++++++--------------- examples/ui/ui_bench.rs | 16 +++++-- src/prelude.rs | 2 +- 10 files changed, 159 insertions(+), 71 deletions(-) create mode 100644 crates/bevy_ui/src/color_material.rs diff --git a/crates/bevy_ui/src/color_material.rs b/crates/bevy_ui/src/color_material.rs new file mode 100644 index 0000000000..9ea05730bb --- /dev/null +++ b/crates/bevy_ui/src/color_material.rs @@ -0,0 +1,55 @@ +use bevy_asset::{self, Handle}; +use bevy_derive::Uniforms; +use bevy_render::{colors, texture::Texture, Color}; + +#[derive(Uniforms)] +#[module(meta = false)] +pub struct ColorMaterial { + pub color: Color, + #[uniform(shader_def)] + pub texture: Option>, +} + +impl ColorMaterial { + pub fn color(color: Color) -> Self { + ColorMaterial { + color, + texture: None, + } + } + + pub fn texture(texture: Handle) -> Self { + ColorMaterial { + color: colors::WHITE, + texture: Some(texture), + } + } + + pub fn modulated_texture(texture: Handle, color: Color) -> Self { + ColorMaterial { + color, + texture: Some(texture), + } + } +} + +impl Default for ColorMaterial { + fn default() -> Self { + ColorMaterial { + color: Color::rgb(1.0, 1.0, 1.0), + texture: None, + } + } +} + +impl From for ColorMaterial { + fn from(color: Color) -> Self { + ColorMaterial::color(color) + } +} + +impl From> for ColorMaterial { + fn from(texture: Handle) -> Self { + ColorMaterial::texture(texture) + } +} \ No newline at end of file diff --git a/crates/bevy_ui/src/entity.rs b/crates/bevy_ui/src/entity.rs index bc268a29c4..b872d2c5b1 100644 --- a/crates/bevy_ui/src/entity.rs +++ b/crates/bevy_ui/src/entity.rs @@ -1,15 +1,16 @@ use super::Node; +use crate::{render::UI_PIPELINE_HANDLE, ColorMaterial, Rect, QUAD_HANDLE}; +use bevy_asset::Handle; use bevy_derive::EntityArchetype; use bevy_render::{mesh::Mesh, Renderable}; -use crate::{Rect, render::UI_PIPELINE_HANDLE, QUAD_HANDLE}; -use bevy_asset::Handle; #[derive(EntityArchetype)] #[module(meta = false)] pub struct UiEntity { pub node: Node, pub rect: Rect, - pub mesh: Handle, // TODO: maybe abstract this out + pub mesh: Handle, // TODO: maybe abstract this out + pub material: Handle, pub renderable: Renderable, } @@ -19,12 +20,11 @@ impl Default for UiEntity { node: Default::default(), rect: Default::default(), mesh: QUAD_HANDLE, + material: Default::default(), renderable: Renderable { - pipelines: vec![ - UI_PIPELINE_HANDLE - ], + pipelines: vec![UI_PIPELINE_HANDLE], ..Default::default() - } + }, } } -} \ No newline at end of file +} diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 3444467126..e7b0d379ab 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -1,4 +1,5 @@ mod anchors; +mod color_material; pub mod entity; mod margins; mod node; @@ -7,34 +8,52 @@ mod render; mod ui_update_system; pub use anchors::*; +pub use color_material::*; pub use margins::*; pub use node::*; pub use rect::*; pub use render::*; pub use ui_update_system::*; -use bevy_app::{AppBuilder, AppPlugin}; -use bevy_render::{mesh::{shape::Quad, Mesh}, render_graph::RenderGraph}; +use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_asset::{AssetStorage, Handle}; +use bevy_render::{ + mesh::{shape::Quad, Mesh}, + render_graph::RenderGraph, + shader::asset_handle_shader_def_system, +}; use glam::Vec2; +use legion::prelude::IntoSystem; #[derive(Default)] pub struct UiPlugin; -pub const QUAD_HANDLE: Handle = Handle::from_bytes([179, 41, 129, 128, 95, 217, 79, 194, 167, 95, 107, 115, 97, 151, 20, 62]); +pub const QUAD_HANDLE: Handle = Handle::from_bytes([ + 179, 41, 129, 128, 95, 217, 79, 194, 167, 95, 107, 115, 97, 151, 20, 62, +]); impl AppPlugin for UiPlugin { fn build(&self, app: &mut AppBuilder) { + let mut color_materials = AssetStorage::::new(); + color_materials.add_default(ColorMaterial::default()); - { - let mut render_graph = app.resources().get_mut::().unwrap(); - render_graph.add_ui_graph(app.resources()); + app.add_resource(color_materials) + .add_system_to_stage( + stage::POST_UPDATE, + asset_handle_shader_def_system::.system(), + ) + .add_system(ui_update_system()); - let mut meshes = app.resources().get_mut::>().unwrap(); - meshes.add_with_handle(QUAD_HANDLE, Mesh::from(Quad { + let resources = app.resources(); + let mut render_graph = resources.get_mut::().unwrap(); + render_graph.add_ui_graph(resources); + + let mut meshes = resources.get_mut::>().unwrap(); + meshes.add_with_handle( + QUAD_HANDLE, + Mesh::from(Quad { size: Vec2::new(1.0, 1.0), - })); - } - app.add_system(ui_update_system()); + }), + ); } } diff --git a/crates/bevy_ui/src/rect.rs b/crates/bevy_ui/src/rect.rs index 4146de2c98..3be26e0b01 100644 --- a/crates/bevy_ui/src/rect.rs +++ b/crates/bevy_ui/src/rect.rs @@ -1,6 +1,5 @@ use bevy_core::bytes::GetBytes; use bevy_derive::Uniform; -use bevy_render::Color; use glam::Vec2; use zerocopy::AsBytes; #[repr(C)] @@ -9,7 +8,6 @@ use zerocopy::AsBytes; pub struct Rect { pub position: Vec2, pub size: Vec2, - pub color: Color, pub z_index: f32, } diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 7dc9095824..ed720067ad 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -2,12 +2,12 @@ use bevy_asset::{AssetStorage, Handle}; use bevy_render::{ draw_target::AssignedMeshesDrawTarget, pipeline::{state_descriptors::*, PipelineDescriptor}, - render_graph::{nodes::{UniformNode, PassNode}, RenderGraph}, + render_graph::{nodes::{UniformNode, PassNode, AssetUniformNode}, RenderGraph}, shader::{Shader, ShaderStage, ShaderStages}, texture::TextureFormat, base_render_graph, }; use legion::prelude::Resources; -use crate::Rect; +use crate::{ColorMaterial, Rect}; pub const UI_PIPELINE_HANDLE: Handle = Handle::from_bytes([ @@ -65,6 +65,8 @@ pub trait UiRenderGraphBuilder { impl UiRenderGraphBuilder for RenderGraph { fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self { + self.add_system_node_named("color_material", AssetUniformNode::::new(false), resources); + self.add_node_edge("color_material", base_render_graph::node::MAIN_PASS).unwrap(); self.add_system_node_named("rect", UniformNode::::new(false), resources); self.add_node_edge("rect", base_render_graph::node::MAIN_PASS).unwrap(); let mut pipelines = resources.get_mut::>().unwrap(); diff --git a/crates/bevy_ui/src/render/ui.frag b/crates/bevy_ui/src/render/ui.frag index 50ec9a991b..1146ac2825 100644 --- a/crates/bevy_ui/src/render/ui.frag +++ b/crates/bevy_ui/src/render/ui.frag @@ -1,9 +1,24 @@ #version 450 -layout(location = 0) in vec4 v_Color; +layout(location = 0) in vec2 v_Uv; layout(location = 0) out vec4 o_Target; +layout(set = 2, binding = 0) uniform ColorMaterial_color { + vec4 Color; +}; + +# ifdef COLORMATERIAL_TEXTURE +layout(set = 3, binding = 0) uniform texture2D ColorMaterial_texture; +layout(set = 3, binding = 1) uniform sampler ColorMaterial_texture_sampler; +# endif + void main() { - o_Target = v_Color; + vec4 color = Color; +# ifdef COLORMATERIAL_TEXTURE + color *= texture( + sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler), + v_Uv); +# endif + o_Target = color; } diff --git a/crates/bevy_ui/src/render/ui.vert b/crates/bevy_ui/src/render/ui.vert index ba943b0d0a..e18da08a0c 100644 --- a/crates/bevy_ui/src/render/ui.vert +++ b/crates/bevy_ui/src/render/ui.vert @@ -4,7 +4,7 @@ layout(location = 0) in vec3 Vertex_Position; layout(location = 1) in vec3 Vertex_Normal; layout(location = 2) in vec2 Vertex_Uv; -layout(location = 0) out vec4 v_Color; +layout(location = 0) out vec2 v_Uv; layout(set = 0, binding = 0) uniform Camera2d { mat4 ViewProj; @@ -13,12 +13,11 @@ layout(set = 0, binding = 0) uniform Camera2d { layout(set = 1, binding = 0) uniform Rect { vec2 Rect_Position; vec2 Rect_Size; - vec4 Rect_Color; float Rect_ZIndex; }; void main() { - v_Color = Rect_Color; + v_Uv = Vertex_Uv; vec3 position = Vertex_Position * vec3(Rect_Size, 0.0); position = position + vec3(Rect_Position + Rect_Size / 2.0, -Rect_ZIndex); gl_Position = ViewProj * vec4(position, 1.0); diff --git a/examples/ui/ui.rs b/examples/ui/ui.rs index a0936b5296..be3b6d2cb3 100644 --- a/examples/ui/ui.rs +++ b/examples/ui/ui.rs @@ -1,5 +1,4 @@ use bevy::prelude::*; -use bevy_ui::Rect; fn main() { App::build() @@ -19,6 +18,18 @@ fn setup(world: &mut World, resources: &mut Resources) { ..Default::default() }); + let mut texture_storage = resources.get_mut::>().unwrap(); + let texture_path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/branding/bevy_logo_dark_big.png" + ); + let texture = Texture::load(TextureType::Png(texture_path.to_string())); + let aspect = texture.height as f32 / texture.width as f32; + let texture_handle = texture_storage.add(texture); + + let mut color_materials = resources.get_mut::>().unwrap(); + let blue_material_handle = color_materials.add(Color::rgb(0.6, 0.6, 1.0).into()); + world .build() // cube @@ -53,10 +64,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.0, 0.0, 0.0, 1.0), Margins::new(10.0, 200.0, 10.0, 10.0), ), - rect: Rect { - color: Color::rgb(0.02, 0.02, 0.02), - ..Default::default() - }, + material: color_materials.add(Color::rgb(0.02, 0.02, 0.02).into()), ..Default::default() }) // top right anchor with vertical fill @@ -66,10 +74,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(1.0, 1.0, 0.0, 1.0), Margins::new(10.0, 100.0, 50.0, 100.0), ), - rect: Rect { - color: Color::rgb(0.02, 0.02, 0.02), - ..Default::default() - }, + material: color_materials.add(Color::rgb(0.02, 0.02, 0.02).into()), ..Default::default() }) // render order test: reddest in the back, whitest in the front @@ -79,10 +84,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.5, 0.5, 0.5, 0.5), Margins::new(0.0, 100.0, 0.0, 100.0), ), - rect: Rect { - color: Color::rgb(1.0, 0.00, 0.0), - ..Default::default() - }, + material: color_materials.add(Color::rgb(1.0, 0.0, 0.0).into()), ..Default::default() }) .add_entity(UiEntity { @@ -91,10 +93,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.5, 0.5, 0.5, 0.5), Margins::new(0.0, 100.0, 0.0, 100.0), ), - rect: Rect { - color: Color::rgb(1.0, 0.3, 0.3), - ..Default::default() - }, + material: color_materials.add(Color::rgb(1.0, 0.3, 0.3).into()), ..Default::default() }) .add_entity(UiEntity { @@ -103,10 +102,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.5, 0.5, 0.5, 0.5), Margins::new(0.0, 100.0, 0.0, 100.0), ), - rect: Rect { - color: Color::rgb(1.0, 0.5, 0.5), - ..Default::default() - }, + material: color_materials.add(Color::rgb(1.0, 0.5, 0.5).into()), ..Default::default() }) .add_entity(UiEntity { @@ -115,10 +111,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.5, 0.5, 0.5, 0.5), Margins::new(0.0, 100.0, 0.0, 100.0), ), - rect: Rect { - color: Color::rgb(1.0, 0.7, 0.7), - ..Default::default() - }, + material: color_materials.add(Color::rgb(1.0, 0.7, 0.7).into()), ..Default::default() }) // parenting @@ -128,10 +121,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.0, 0.0, 0.0, 0.0), Margins::new(0.0, 200.0, 0.0, 200.0), ), - rect: Rect { - color: Color::rgb(0.1, 0.1, 1.0), - ..Default::default() - }, + material: color_materials.add(Color::rgb(0.1, 0.1, 1.0).into()), ..Default::default() }) .add_children(|builder| { @@ -141,10 +131,7 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.0, 1.0, 0.0, 1.0), Margins::new(20.0, 20.0, 20.0, 20.0), ), - rect: Rect { - color: Color::rgb(0.6, 0.6, 1.0), - ..Default::default() - }, + material: blue_material_handle, ..Default::default() }); }) @@ -155,10 +142,17 @@ fn setup(world: &mut World, resources: &mut Resources) { Anchors::new(0.5, 0.5, 0.5, 0.5), Margins::new(0.0, 100.0, 0.0, 100.0), ), - rect: Rect { - color: Color::rgba(1.0, 0.9, 0.9, 0.4), - ..Default::default() - }, + material: color_materials.add(Color::rgba(1.0, 0.9, 0.9, 0.4).into()), + ..Default::default() + }) + // texture + .add_entity(UiEntity { + node: Node::new( + math::vec2(400.0, 100.0), + Anchors::new(0.0, 0.0, 0.0, 0.0), + Margins::new(0.0, 500.0, 0.0, 500.0 * aspect), + ), + material: color_materials.add(ColorMaterial::texture(texture_handle)), ..Default::default() }); } diff --git a/examples/ui/ui_bench.rs b/examples/ui/ui_bench.rs index a3df4db1d7..e8fe1b1cee 100644 --- a/examples/ui/ui_bench.rs +++ b/examples/ui/ui_bench.rs @@ -1,11 +1,11 @@ use bevy::prelude::*; -use bevy_ui::Rect; +use bevy_ui::{ColorMaterial, Rect}; fn main() { App::build() .add_default_plugins() .add_startup_system(setup) - .add_system(move_system.system()) + .add_system(placement_system.system()) .add_plugin(DiagnosticsPlugin { print_diagnostics: true, ..Default::default() @@ -13,8 +13,14 @@ fn main() { .run(); } -fn move_system(time: Resource