ui textures

This commit is contained in:
Carter Anderson 2020-05-03 23:49:45 -07:00
parent 08c6679f38
commit 1056b79abf
10 changed files with 159 additions and 71 deletions

View file

@ -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<Handle<Texture>>,
}
impl ColorMaterial {
pub fn color(color: Color) -> Self {
ColorMaterial {
color,
texture: None,
}
}
pub fn texture(texture: Handle<Texture>) -> Self {
ColorMaterial {
color: colors::WHITE,
texture: Some(texture),
}
}
pub fn modulated_texture(texture: Handle<Texture>, 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<Color> for ColorMaterial {
fn from(color: Color) -> Self {
ColorMaterial::color(color)
}
}
impl From<Handle<Texture>> for ColorMaterial {
fn from(texture: Handle<Texture>) -> Self {
ColorMaterial::texture(texture)
}
}

View file

@ -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<Mesh>, // TODO: maybe abstract this out
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
pub material: Handle<ColorMaterial>,
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()
}
},
}
}
}

View file

@ -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<Mesh> = Handle::from_bytes([179, 41, 129, 128, 95, 217, 79, 194, 167, 95, 107, 115, 97, 151, 20, 62]);
pub const QUAD_HANDLE: Handle<Mesh> = 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::<ColorMaterial>::new();
color_materials.add_default(ColorMaterial::default());
{
let mut render_graph = app.resources().get_mut::<RenderGraph>().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::<ColorMaterial>.system(),
)
.add_system(ui_update_system());
let mut meshes = app.resources().get_mut::<AssetStorage<Mesh>>().unwrap();
meshes.add_with_handle(QUAD_HANDLE, Mesh::from(Quad {
let resources = app.resources();
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
render_graph.add_ui_graph(resources);
let mut meshes = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
meshes.add_with_handle(
QUAD_HANDLE,
Mesh::from(Quad {
size: Vec2::new(1.0, 1.0),
}));
}
app.add_system(ui_update_system());
}),
);
}
}

View file

@ -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,
}

View file

@ -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<PipelineDescriptor> =
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::<ColorMaterial>::new(false), resources);
self.add_node_edge("color_material", base_render_graph::node::MAIN_PASS).unwrap();
self.add_system_node_named("rect", UniformNode::<Rect>::new(false), resources);
self.add_node_edge("rect", base_render_graph::node::MAIN_PASS).unwrap();
let mut pipelines = resources.get_mut::<AssetStorage<PipelineDescriptor>>().unwrap();

View file

@ -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;
}

View file

@ -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);

View file

@ -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::<AssetStorage<Texture>>().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::<AssetStorage<ColorMaterial>>().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()
});
}

View file

@ -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<Time>, mut node: RefMut<Node>, rect: Ref<Rect>) {
if rect.color.r > 0.2 {
fn placement_system(
time: Resource<Time>,
materials: Resource<AssetStorage<ColorMaterial>>,
mut node: RefMut<Node>,
material_handle: Ref<Handle<ColorMaterial>>,
) {
let material = materials.get(&material_handle).unwrap();
if material.color.r > 0.2 {
node.position += Vec2::new(0.1 * time.delta_seconds, 0.0);
}
}
@ -38,7 +44,7 @@ fn setup(world: &mut World, _resources: &mut Resources) {
Margins::new(0.0, 100.0, 0.0, 100.0),
),
rect: Rect {
color: Color::rgb(0.0 + i as f32 / count as f32, 0.1, 0.1),
// color: Color::rgb(0.0 + i as f32 / count as f32, 0.1, 0.1),
..Default::default()
},
..Default::default()

View file

@ -32,7 +32,7 @@ pub use crate::render::{
#[cfg(feature = "transform")]
pub use crate::transform::prelude::*;
#[cfg(feature = "ui")]
pub use crate::ui::{entity::*, Anchors, Margins, Node};
pub use crate::ui::{entity::*, Anchors, Margins, Node, ColorMaterial};
#[cfg(feature = "window")]
pub use crate::window::{Window, WindowDescriptor, WindowPlugin, Windows};
pub use crate::{