mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
sprite: create sprite crate. center 2d camera (split from ui camera). add 2d camera movement
This commit is contained in:
parent
71b3755633
commit
6e76296ce0
31 changed files with 445 additions and 220 deletions
|
@ -6,7 +6,7 @@ edition = "2018"
|
|||
|
||||
[features]
|
||||
default = ["headless", "wgpu", "winit"]
|
||||
headless = ["asset", "type_registry", "core", "derive", "diagnostic", "gltf", "input", "pbr", "property", "render", "scene", "text", "transform", "ui", "window"]
|
||||
headless = ["asset", "type_registry", "core", "derive", "diagnostic", "gltf", "input", "pbr", "property", "render", "scene", "sprite", "text", "transform", "ui", "window"]
|
||||
asset = ["bevy_asset"]
|
||||
core = ["bevy_core"]
|
||||
type_registry = ["bevy_type_registry"]
|
||||
|
@ -18,6 +18,7 @@ pbr = ["bevy_pbr"]
|
|||
property = ["bevy_property"]
|
||||
render = ["bevy_render"]
|
||||
scene = ["bevy_scene"]
|
||||
sprite = ["bevy_sprite"]
|
||||
text = ["bevy_text"]
|
||||
transform = ["bevy_transform"]
|
||||
ui = ["bevy_ui"]
|
||||
|
@ -50,6 +51,7 @@ bevy_pbr = { path = "crates/bevy_pbr", optional = true }
|
|||
bevy_property = { path = "crates/bevy_property", optional = true }
|
||||
bevy_render = { path = "crates/bevy_render", optional = true }
|
||||
bevy_scene = { path = "crates/bevy_scene", optional = true }
|
||||
bevy_sprite = { path = "crates/bevy_sprite", optional = true }
|
||||
bevy_transform = { path = "crates/bevy_transform", optional = true }
|
||||
bevy_text = { path = "crates/bevy_text", optional = true }
|
||||
bevy_ui = { path = "crates/bevy_ui", optional = true }
|
||||
|
|
|
@ -19,6 +19,10 @@ pub mod node {
|
|||
pub const LIGHTS: &str = "lights";
|
||||
}
|
||||
|
||||
pub mod uniform {
|
||||
pub const LIGHTS: &str = "Lights";
|
||||
}
|
||||
|
||||
pub trait ForwardPbrRenderGraphBuilder {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy_render::{Color, PerspectiveCamera, CameraProjection};
|
||||
use bevy_render::{Color, PerspectiveProjection, CameraProjection};
|
||||
use bevy_transform::components::Translation;
|
||||
use bevy_property::Properties;
|
||||
use glam::Mat4;
|
||||
|
@ -32,7 +32,7 @@ pub struct LightRaw {
|
|||
|
||||
impl LightRaw {
|
||||
pub fn from(light: &Light, transform: &Mat4, translation: &Translation) -> LightRaw {
|
||||
let perspective = PerspectiveCamera {
|
||||
let perspective = PerspectiveProjection {
|
||||
fov: light.fov,
|
||||
aspect_ratio: 1.0,
|
||||
near: light.depth.start,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use bevy_render::{
|
||||
base_render_graph,
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{
|
||||
BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
|
||||
|
@ -7,7 +6,10 @@ use bevy_render::{
|
|||
renderer::{RenderContext, RenderResources},
|
||||
};
|
||||
|
||||
use crate::light::{Light, LightRaw};
|
||||
use crate::{
|
||||
light::{Light, LightRaw},
|
||||
uniform,
|
||||
};
|
||||
use bevy_transform::prelude::*;
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
@ -77,7 +79,7 @@ impl SystemNode for LightsNode {
|
|||
..Default::default()
|
||||
});
|
||||
render_resource_assignments.set(
|
||||
base_render_graph::uniform::LIGHTS,
|
||||
uniform::LIGHTS,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: buffer,
|
||||
range: 0..light_uniform_size as u64,
|
||||
|
|
|
@ -41,7 +41,6 @@ pub mod node {
|
|||
pub mod uniform {
|
||||
pub const CAMERA: &str = "Camera";
|
||||
pub const CAMERA2D: &str = "Camera2d";
|
||||
pub const LIGHTS: &str = "Lights";
|
||||
}
|
||||
|
||||
impl Default for BaseRenderGraphConfig {
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
use bevy_app::{Events, GetEventReader};
|
||||
use bevy_property::Properties;
|
||||
use bevy_window::WindowResized;
|
||||
use glam::Mat4;
|
||||
use legion::{prelude::*, storage::Component};
|
||||
|
||||
#[derive(Debug, Clone, Properties)]
|
||||
pub struct OrthographicCamera {
|
||||
pub left: f32,
|
||||
pub right: f32,
|
||||
pub bottom: f32,
|
||||
pub top: f32,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
}
|
||||
|
||||
impl CameraProjection for OrthographicCamera {
|
||||
fn get_view_matrix(&self) -> Mat4 {
|
||||
let projection = Mat4::orthographic_rh_gl(
|
||||
self.left,
|
||||
self.right,
|
||||
self.bottom,
|
||||
self.top,
|
||||
self.near,
|
||||
self.far,
|
||||
);
|
||||
projection
|
||||
}
|
||||
fn update(&mut self, width: usize, height: usize) {
|
||||
self.right = width as f32;
|
||||
self.top = height as f32;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OrthographicCamera {
|
||||
fn default() -> Self {
|
||||
OrthographicCamera {
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 0.0,
|
||||
top: 0.0,
|
||||
near: 0.0,
|
||||
far: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CameraProjection {
|
||||
fn get_view_matrix(&self) -> Mat4;
|
||||
fn update(&mut self, width: usize, height: usize);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Properties)]
|
||||
pub struct PerspectiveCamera {
|
||||
pub fov: f32,
|
||||
pub aspect_ratio: f32,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
}
|
||||
|
||||
impl CameraProjection for PerspectiveCamera {
|
||||
fn get_view_matrix(&self) -> Mat4 {
|
||||
let projection = Mat4::perspective_rh_gl(self.fov, self.aspect_ratio, self.near, self.far);
|
||||
projection
|
||||
}
|
||||
fn update(&mut self, width: usize, height: usize) {
|
||||
self.aspect_ratio = width as f32 / height as f32;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PerspectiveCamera {
|
||||
fn default() -> Self {
|
||||
PerspectiveCamera {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Properties)]
|
||||
pub struct Camera {
|
||||
pub view_matrix: Mat4,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
pub fn camera_system<T: CameraProjection + Component>(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
||||
(move |world: &mut SubWorld,
|
||||
window_resized_events: Res<Events<WindowResized>>,
|
||||
query: &mut Query<(Write<Camera>, Write<T>)>| {
|
||||
let primary_window_resized_event = window_resized_event_reader
|
||||
.find_latest(&window_resized_events, |event| event.is_primary);
|
||||
if let Some(primary_window_resized_event) = primary_window_resized_event {
|
||||
for (mut camera, mut camera_projection) in query.iter_mut(world) {
|
||||
camera_projection.update(primary_window_resized_event.width, primary_window_resized_event.height);
|
||||
camera.view_matrix = camera_projection.get_view_matrix();
|
||||
}
|
||||
}
|
||||
})
|
||||
.system()
|
||||
}
|
34
crates/bevy_render/src/camera/camera.rs
Normal file
34
crates/bevy_render/src/camera/camera.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
use crate::CameraProjection;
|
||||
use bevy_app::{Events, GetEventReader};
|
||||
use bevy_property::Properties;
|
||||
use bevy_window::WindowResized;
|
||||
use glam::Mat4;
|
||||
use legion::{prelude::*, storage::Component};
|
||||
|
||||
#[derive(Default, Debug, Properties)]
|
||||
pub struct Camera {
|
||||
pub view_matrix: Mat4,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
pub fn camera_system<T: CameraProjection + Component>(
|
||||
resources: &mut Resources,
|
||||
) -> Box<dyn Schedulable> {
|
||||
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
||||
(move |world: &mut SubWorld,
|
||||
window_resized_events: Res<Events<WindowResized>>,
|
||||
query: &mut Query<(Write<Camera>, Write<T>)>| {
|
||||
let primary_window_resized_event = window_resized_event_reader
|
||||
.find_latest(&window_resized_events, |event| event.is_primary);
|
||||
if let Some(primary_window_resized_event) = primary_window_resized_event {
|
||||
for (mut camera, mut camera_projection) in query.iter_mut(world) {
|
||||
camera_projection.update(
|
||||
primary_window_resized_event.width,
|
||||
primary_window_resized_event.height,
|
||||
);
|
||||
camera.view_matrix = camera_projection.get_view_matrix();
|
||||
}
|
||||
}
|
||||
})
|
||||
.system()
|
||||
}
|
5
crates/bevy_render/src/camera/mod.rs
Normal file
5
crates/bevy_render/src/camera/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod camera;
|
||||
mod projection;
|
||||
|
||||
pub use camera::*;
|
||||
pub use projection::*;
|
100
crates/bevy_render/src/camera/projection.rs
Normal file
100
crates/bevy_render/src/camera/projection.rs
Normal file
|
@ -0,0 +1,100 @@
|
|||
use bevy_property::{Properties, Property};
|
||||
use glam::Mat4;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub trait CameraProjection {
|
||||
fn get_view_matrix(&self) -> Mat4;
|
||||
fn update(&mut self, width: usize, height: usize);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Properties)]
|
||||
pub struct PerspectiveProjection {
|
||||
pub fov: f32,
|
||||
pub aspect_ratio: f32,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
}
|
||||
|
||||
impl CameraProjection for PerspectiveProjection {
|
||||
fn get_view_matrix(&self) -> Mat4 {
|
||||
let projection = Mat4::perspective_rh_gl(self.fov, self.aspect_ratio, self.near, self.far);
|
||||
projection
|
||||
}
|
||||
fn update(&mut self, width: usize, height: usize) {
|
||||
self.aspect_ratio = width as f32 / height as f32;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PerspectiveProjection {
|
||||
fn default() -> Self {
|
||||
PerspectiveProjection {
|
||||
fov: std::f32::consts::PI / 4.0,
|
||||
near: 1.0,
|
||||
far: 1000.0,
|
||||
aspect_ratio: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Property, Serialize, Deserialize)]
|
||||
pub enum WindowOrigin {
|
||||
Center,
|
||||
BottomLeft,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Properties)]
|
||||
pub struct OrthographicProjection {
|
||||
pub left: f32,
|
||||
pub right: f32,
|
||||
pub bottom: f32,
|
||||
pub top: f32,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
pub window_origin: WindowOrigin,
|
||||
}
|
||||
|
||||
impl CameraProjection for OrthographicProjection {
|
||||
fn get_view_matrix(&self) -> Mat4 {
|
||||
let projection = Mat4::orthographic_rh_gl(
|
||||
self.left,
|
||||
self.right,
|
||||
self.bottom,
|
||||
self.top,
|
||||
self.near,
|
||||
self.far,
|
||||
);
|
||||
projection
|
||||
}
|
||||
fn update(&mut self, width: usize, height: usize) {
|
||||
match self.window_origin {
|
||||
WindowOrigin::Center => {
|
||||
let half_width = width as f32 / 2.0;
|
||||
let half_height = height as f32 / 2.0;
|
||||
self.left = -half_width;
|
||||
self.right = half_width;
|
||||
self.top = half_height;
|
||||
self.bottom = -half_height;
|
||||
}
|
||||
WindowOrigin::BottomLeft => {
|
||||
self.left = 0.0;
|
||||
self.right = width as f32;
|
||||
self.top = height as f32;
|
||||
self.bottom = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OrthographicProjection {
|
||||
fn default() -> Self {
|
||||
OrthographicProjection {
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 0.0,
|
||||
top: 0.0,
|
||||
near: 0.0,
|
||||
far: 1.0,
|
||||
window_origin: WindowOrigin::Center,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{mesh::Mesh, Camera, Renderable, OrthographicCamera, PerspectiveCamera, base_render_graph};
|
||||
use crate::{mesh::Mesh, Camera, Renderable, OrthographicProjection, PerspectiveProjection, base_render_graph};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::EntityArchetype;
|
||||
use bevy_transform::components::{LocalToWorld, Rotation, Scale, Translation};
|
||||
|
@ -17,7 +17,7 @@ pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
|
|||
#[derive(EntityArchetype)]
|
||||
pub struct PerspectiveCameraEntity {
|
||||
pub camera: Camera,
|
||||
pub perspective_camera: PerspectiveCamera,
|
||||
pub perspective_projection: PerspectiveProjection,
|
||||
pub local_to_world: LocalToWorld,
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ impl Default for PerspectiveCameraEntity {
|
|||
name: Some(base_render_graph::uniform::CAMERA.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
perspective_camera: Default::default(),
|
||||
perspective_projection: Default::default(),
|
||||
local_to_world: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,10 @@ impl Default for PerspectiveCameraEntity {
|
|||
#[derive(EntityArchetype)]
|
||||
pub struct OrthographicCameraEntity {
|
||||
pub camera: Camera,
|
||||
pub orthographic_camera: OrthographicCamera,
|
||||
pub orthographic_projection: OrthographicProjection,
|
||||
pub local_to_world: LocalToWorld,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
}
|
||||
|
||||
impl OrthographicCameraEntity {
|
||||
|
@ -49,8 +51,10 @@ impl OrthographicCameraEntity {
|
|||
name: Some("UiCamera".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
orthographic_camera: Default::default(),
|
||||
orthographic_projection: Default::default(),
|
||||
local_to_world: Default::default(),
|
||||
translation: Default::default(),
|
||||
rotation: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,8 +66,10 @@ impl Default for OrthographicCameraEntity {
|
|||
name: Some(base_render_graph::uniform::CAMERA2D.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
orthographic_camera: Default::default(),
|
||||
orthographic_projection: Default::default(),
|
||||
local_to_world: Default::default(),
|
||||
translation: Default::default(),
|
||||
rotation: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ impl AppPlugin for RenderPlugin {
|
|||
.add_asset::<PipelineDescriptor>()
|
||||
.add_asset_loader::<Texture, PngTextureLoader>()
|
||||
.register_component::<Camera>()
|
||||
.register_component::<OrthographicCamera>()
|
||||
.register_component::<PerspectiveCamera>()
|
||||
.register_component::<OrthographicProjection>()
|
||||
.register_component::<PerspectiveProjection>()
|
||||
.register_component::<Renderable>()
|
||||
.register_property_type::<Color>()
|
||||
.register_property_type::<Range<f32>>()
|
||||
|
@ -90,8 +90,8 @@ impl AppPlugin for RenderPlugin {
|
|||
.init_resource::<EntitiesWaitingForAssets>()
|
||||
.init_resource::<TextureResourceSystemState>()
|
||||
.add_system(entity_render_resource_assignments_system())
|
||||
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<OrthographicCamera>)
|
||||
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<PerspectiveCamera>)
|
||||
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<OrthographicProjection>)
|
||||
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<PerspectiveProjection>)
|
||||
.add_system_to_stage(
|
||||
stage::PRE_UPDATE,
|
||||
EntitiesWaitingForAssets::clear_system.system(),
|
||||
|
|
18
crates/bevy_sprite/Cargo.toml
Normal file
18
crates/bevy_sprite/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "bevy_sprite"
|
||||
version = "0.1.0"
|
||||
authors = ["Carter Anderson <mcanders1@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bevy_app = { path = "../bevy_app" }
|
||||
bevy_core = { path = "../bevy_core" }
|
||||
bevy_asset = { path = "../bevy_asset" }
|
||||
bevy_type_registry = { path = "../bevy_type_registry" }
|
||||
bevy_derive = { path = "../bevy_derive" }
|
||||
bevy_render = { path = "../bevy_render" }
|
||||
glam = { path = "../bevy_glam" }
|
||||
legion = { path = "../bevy_legion", features = ["serialize"] }
|
||||
zerocopy = "0.3.0"
|
30
crates/bevy_sprite/src/entity.rs
Normal file
30
crates/bevy_sprite/src/entity.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use crate::{
|
||||
render::SPRITE_PIPELINE_HANDLE, sprite::Sprite, ColorMaterial, Rect, QUAD_HANDLE,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::EntityArchetype;
|
||||
use bevy_render::{mesh::Mesh, Renderable};
|
||||
|
||||
#[derive(EntityArchetype)]
|
||||
pub struct SpriteEntity {
|
||||
pub sprite: Sprite,
|
||||
pub rect: Rect,
|
||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||
pub material: Handle<ColorMaterial>,
|
||||
pub renderable: Renderable,
|
||||
}
|
||||
|
||||
impl Default for SpriteEntity {
|
||||
fn default() -> Self {
|
||||
SpriteEntity {
|
||||
sprite: Default::default(),
|
||||
rect: Default::default(),
|
||||
mesh: QUAD_HANDLE,
|
||||
material: Default::default(),
|
||||
renderable: Renderable {
|
||||
pipelines: vec![SPRITE_PIPELINE_HANDLE],
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
52
crates/bevy_sprite/src/lib.rs
Normal file
52
crates/bevy_sprite/src/lib.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
mod color_material;
|
||||
pub mod entity;
|
||||
mod rect;
|
||||
mod render;
|
||||
mod sprite;
|
||||
|
||||
pub use color_material::*;
|
||||
pub use rect::*;
|
||||
pub use render::*;
|
||||
pub use sprite::*;
|
||||
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_asset::{AddAsset, Assets, Handle};
|
||||
use bevy_render::{
|
||||
mesh::{shape::Quad, Mesh},
|
||||
render_graph::RenderGraph,
|
||||
shader::asset_shader_def_system,
|
||||
};
|
||||
use glam::Vec2;
|
||||
use legion::prelude::IntoSystem;
|
||||
use sprite::sprite_system;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SpritePlugin;
|
||||
|
||||
pub const QUAD_HANDLE: Handle<Mesh> = Handle::from_u128(142404619811301375266013514540294236421);
|
||||
|
||||
impl AppPlugin for SpritePlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.add_asset::<ColorMaterial>()
|
||||
.add_system_to_stage(stage::POST_UPDATE, sprite_system())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
asset_shader_def_system::<ColorMaterial>.system(),
|
||||
);
|
||||
|
||||
let resources = app.resources();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_sprite_graph(resources);
|
||||
|
||||
let mut meshes = resources.get_mut::<Assets<Mesh>>().unwrap();
|
||||
meshes.set(
|
||||
QUAD_HANDLE,
|
||||
Mesh::from(Quad {
|
||||
size: Vec2::new(1.0, 1.0),
|
||||
}),
|
||||
);
|
||||
|
||||
let mut color_materials = resources.get_mut::<Assets<ColorMaterial>>().unwrap();
|
||||
color_materials.add_default(ColorMaterial::default());
|
||||
}
|
||||
}
|
98
crates/bevy_sprite/src/render/mod.rs
Normal file
98
crates/bevy_sprite/src/render/mod.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
use crate::{ColorMaterial, Rect};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_render::{
|
||||
base_render_graph,
|
||||
draw_target::AssignedMeshesDrawTarget,
|
||||
pipeline::{state_descriptors::*, PipelineDescriptor},
|
||||
render_graph::{
|
||||
nodes::{AssetUniformNode, PassNode, UniformNode},
|
||||
RenderGraph,
|
||||
},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
use legion::prelude::Resources;
|
||||
|
||||
pub const SPRITE_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
||||
Handle::from_u128(278534784033876544639935131272264723170);
|
||||
|
||||
pub fn build_sprite_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
PipelineDescriptor {
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
}],
|
||||
..PipelineDescriptor::new(ShaderStages {
|
||||
vertex: shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("sprite.vert"),
|
||||
)),
|
||||
fragment: Some(shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("sprite.frag"),
|
||||
))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub mod node {
|
||||
pub const COLOR_MATERIAL: &'static str = "color_material";
|
||||
pub const RECT: &'static str = "rect";
|
||||
}
|
||||
|
||||
pub trait SpriteRenderGraphBuilder {
|
||||
fn add_sprite_graph(&mut self, resources: &Resources) -> &mut Self;
|
||||
}
|
||||
|
||||
impl SpriteRenderGraphBuilder for RenderGraph {
|
||||
fn add_sprite_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node(
|
||||
node::COLOR_MATERIAL,
|
||||
AssetUniformNode::<ColorMaterial>::new(false),
|
||||
);
|
||||
self.add_node_edge(node::COLOR_MATERIAL, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
self.add_system_node(node::RECT, UniformNode::<Rect>::new(false));
|
||||
self.add_node_edge(node::RECT, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||
pipelines.set(SPRITE_PIPELINE_HANDLE, build_sprite_pipeline(&mut shaders));
|
||||
let main_pass: &mut PassNode = self
|
||||
.get_node_mut(base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
main_pass.add_pipeline(
|
||||
SPRITE_PIPELINE_HANDLE,
|
||||
vec![Box::new(AssignedMeshesDrawTarget)],
|
||||
);
|
||||
self
|
||||
}
|
||||
}
|
24
crates/bevy_sprite/src/render/sprite.frag
Normal file
24
crates/bevy_sprite/src/render/sprite.frag
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
|
||||
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() {
|
||||
vec4 color = Color;
|
||||
# ifdef COLORMATERIAL_TEXTURE
|
||||
color *= texture(
|
||||
sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler),
|
||||
v_Uv);
|
||||
# endif
|
||||
o_Target = color;
|
||||
}
|
24
crates/bevy_sprite/src/render/sprite.vert
Normal file
24
crates/bevy_sprite/src/render/sprite.vert
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
|
||||
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 vec2 v_Uv;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera2d {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform Rect {
|
||||
vec2 Rect_Position;
|
||||
vec2 Rect_Size;
|
||||
float Rect_ZIndex;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Uv = Vertex_Uv;
|
||||
vec3 position = Vertex_Position * vec3(Rect_Size, 0.0);
|
||||
position = position + vec3(Rect_Position, -Rect_ZIndex);
|
||||
gl_Position = ViewProj * vec4(position, 1.0);
|
||||
}
|
|
@ -10,6 +10,7 @@ bevy_asset = { path = "../bevy_asset" }
|
|||
bevy_type_registry = { path = "../bevy_type_registry" }
|
||||
bevy_core = { path = "../bevy_core" }
|
||||
bevy_derive = { path = "../bevy_derive" }
|
||||
bevy_sprite = { path = "../bevy_sprite" }
|
||||
bevy_text = { path = "../bevy_text" }
|
||||
bevy_transform = { path = "../bevy_transform" }
|
||||
bevy_render = { path = "../bevy_render" }
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use super::Node;
|
||||
use crate::{
|
||||
render::UI_PIPELINE_HANDLE, sprite::Sprite, widget::Label, ColorMaterial, Rect, QUAD_HANDLE,
|
||||
};
|
||||
use crate::{render::UI_PIPELINE_HANDLE, widget::Label};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::EntityArchetype;
|
||||
use bevy_render::{mesh::Mesh, Renderable};
|
||||
use bevy_sprite::{ColorMaterial, Rect, QUAD_HANDLE};
|
||||
|
||||
#[derive(EntityArchetype)]
|
||||
pub struct UiEntity {
|
||||
|
@ -56,27 +55,3 @@ impl Default for LabelEntity {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(EntityArchetype)]
|
||||
pub struct SpriteEntity {
|
||||
pub sprite: Sprite,
|
||||
pub rect: Rect,
|
||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||
pub material: Handle<ColorMaterial>,
|
||||
pub renderable: Renderable,
|
||||
}
|
||||
|
||||
impl Default for SpriteEntity {
|
||||
fn default() -> Self {
|
||||
SpriteEntity {
|
||||
sprite: Default::default(),
|
||||
rect: Default::default(),
|
||||
mesh: QUAD_HANDLE,
|
||||
material: Default::default(),
|
||||
renderable: Renderable {
|
||||
pipelines: vec![UI_PIPELINE_HANDLE],
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,64 +1,32 @@
|
|||
mod anchors;
|
||||
mod color_material;
|
||||
pub mod entity;
|
||||
pub mod widget;
|
||||
mod margins;
|
||||
mod node;
|
||||
mod rect;
|
||||
mod render;
|
||||
mod sprite;
|
||||
mod ui_update_system;
|
||||
pub mod widget;
|
||||
|
||||
pub use anchors::*;
|
||||
pub use color_material::*;
|
||||
pub use margins::*;
|
||||
pub use node::*;
|
||||
pub use rect::*;
|
||||
pub use render::*;
|
||||
pub use sprite::*;
|
||||
pub use ui_update_system::*;
|
||||
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_asset::{AddAsset, Assets, Handle};
|
||||
use bevy_render::{
|
||||
mesh::{shape::Quad, Mesh},
|
||||
render_graph::RenderGraph,
|
||||
shader::asset_shader_def_system,
|
||||
};
|
||||
use glam::Vec2;
|
||||
use bevy_render::render_graph::RenderGraph;
|
||||
use legion::prelude::IntoSystem;
|
||||
use sprite::sprite_system;
|
||||
use widget::Label;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UiPlugin;
|
||||
|
||||
pub const QUAD_HANDLE: Handle<Mesh> = Handle::from_u128(142404619811301375266013514540294236421);
|
||||
|
||||
impl AppPlugin for UiPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.add_asset::<ColorMaterial>()
|
||||
.add_system_to_stage(stage::POST_UPDATE, sprite_system())
|
||||
.add_system_to_stage(stage::POST_UPDATE, ui_update_system())
|
||||
.add_system_to_stage(stage::POST_UPDATE, Label::label_system.system())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
asset_shader_def_system::<ColorMaterial>.system(),
|
||||
);
|
||||
app.add_system_to_stage(stage::POST_UPDATE, ui_update_system())
|
||||
.add_system_to_stage(stage::POST_UPDATE, Label::label_system.system());
|
||||
|
||||
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::<Assets<Mesh>>().unwrap();
|
||||
meshes.set(
|
||||
QUAD_HANDLE,
|
||||
Mesh::from(Quad {
|
||||
size: Vec2::new(1.0, 1.0),
|
||||
}),
|
||||
);
|
||||
|
||||
let mut color_materials = resources.get_mut::<Assets<ColorMaterial>>().unwrap();
|
||||
color_materials.add_default(ColorMaterial::default());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Anchors, Margins};
|
||||
use crate::Rect;
|
||||
use bevy_sprite::Rect;
|
||||
use glam::Vec2;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use crate::{ColorMaterial, Rect};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_render::{
|
||||
base_render_graph,
|
||||
draw_target::AssignedMeshesDrawTarget,
|
||||
pipeline::{state_descriptors::*, PipelineDescriptor},
|
||||
render_graph::{
|
||||
nodes::{AssetUniformNode, PassNode, UniformNode, CameraNode},
|
||||
nodes::{CameraNode, PassNode},
|
||||
RenderGraph,
|
||||
},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
|
@ -62,9 +61,7 @@ pub fn build_ui_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
|||
}
|
||||
|
||||
pub mod node {
|
||||
pub const COLOR_MATERIAL: &'static str = "color_material";
|
||||
pub const UI_CAMERA: &'static str = "ui_camera";
|
||||
pub const RECT: &'static str = "rect";
|
||||
}
|
||||
|
||||
pub mod uniform {
|
||||
|
@ -77,21 +74,9 @@ pub trait UiRenderGraphBuilder {
|
|||
|
||||
impl UiRenderGraphBuilder for RenderGraph {
|
||||
fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node(
|
||||
node::COLOR_MATERIAL,
|
||||
AssetUniformNode::<ColorMaterial>::new(false),
|
||||
);
|
||||
self.add_node_edge(node::COLOR_MATERIAL, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
self.add_system_node(node::UI_CAMERA, CameraNode::new(uniform::UI_CAMERA));
|
||||
self.add_node_edge(node::UI_CAMERA, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
self.add_system_node(node::RECT, UniformNode::<Rect>::new(false));
|
||||
self.add_node_edge(node::RECT, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::Node;
|
||||
use crate::Rect;
|
||||
use bevy_core::transform::run_on_hierarchy_subworld_mut;
|
||||
use bevy_transform::prelude::{Children, Parent};
|
||||
use bevy_window::Windows;
|
||||
use glam::Vec2;
|
||||
use legion::{prelude::*, systems::SubWorld};
|
||||
use bevy_sprite::Rect;
|
||||
|
||||
pub const UI_Z_STEP: f32 = 0.0001;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{ColorMaterial, Rect, Res, ResMut};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_render::{texture::Texture, Color};
|
||||
use bevy_sprite::{ColorMaterial, Rect};
|
||||
use bevy_text::Font;
|
||||
use legion::prelude::Com;
|
||||
use legion::prelude::{Com, Res, ResMut};
|
||||
|
||||
pub struct Label {
|
||||
pub text: String,
|
||||
|
@ -37,17 +37,14 @@ impl Label {
|
|||
let height = rect.size.y().max(1.0);
|
||||
|
||||
if let Some(font) = fonts.get(&label.font) {
|
||||
let texture = font.render_text(
|
||||
&label.text,
|
||||
label.color,
|
||||
width as usize,
|
||||
height as usize,
|
||||
);
|
||||
let texture =
|
||||
font.render_text(&label.text, label.color, width as usize, height as usize);
|
||||
|
||||
let material = color_materials.get_or_insert_with(*color_material_handle, || ColorMaterial::from(Handle::<Texture>::new()));
|
||||
let material = color_materials.get_or_insert_with(*color_material_handle, || {
|
||||
ColorMaterial::from(Handle::<Texture>::new())
|
||||
});
|
||||
if let Some(texture_handle) = material.texture {
|
||||
textures.set(texture_handle, texture);
|
||||
|
||||
} else {
|
||||
material.texture = Some(textures.add(texture));
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ fn setup(
|
|||
let texture_handle = asset_server.load("assets/branding/icon.png").unwrap();
|
||||
command_buffer
|
||||
.build()
|
||||
.add_entity(OrthographicCameraEntity::ui())
|
||||
.add_entity(OrthographicCameraEntity::default())
|
||||
.add_entity(SpriteEntity {
|
||||
rect: Rect {
|
||||
position: Vec2::new(300.0, 300.0),
|
||||
position: Vec2::new(0.0, 0.0),
|
||||
z_index: 0.5,
|
||||
..Default::default()
|
||||
},
|
||||
|
|
|
@ -30,6 +30,9 @@ impl AddDefaultPlugins for AppBuilder {
|
|||
#[cfg(feature = "render")]
|
||||
self.add_plugin(bevy_render::RenderPlugin::default());
|
||||
|
||||
#[cfg(feature = "sprite")]
|
||||
self.add_plugin(bevy_sprite::SpritePlugin::default());
|
||||
|
||||
#[cfg(feature = "pbr")]
|
||||
self.add_plugin(bevy_pbr::PbrPlugin::default());
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ pub use bevy_property as property;
|
|||
pub use bevy_render as render;
|
||||
#[cfg(feature = "scene")]
|
||||
pub use bevy_scene as scene;
|
||||
#[cfg(feature = "sprite")]
|
||||
pub use bevy_sprite as sprite;
|
||||
#[cfg(feature = "text")]
|
||||
pub use bevy_text as text;
|
||||
#[cfg(feature = "transform")]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
pub use crate::app::FromResources;
|
||||
#[cfg(feature = "asset")]
|
||||
pub use crate::asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle};
|
||||
#[cfg(feature = "core")]
|
||||
|
@ -29,10 +28,12 @@ pub use crate::render::{
|
|||
},
|
||||
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages},
|
||||
texture::{Texture, TextureType},
|
||||
Camera, OrthographicCamera, PerspectiveCamera, Color, ColorSource, Renderable,
|
||||
Camera, Color, ColorSource, OrthographicProjection, PerspectiveProjection, Renderable,
|
||||
};
|
||||
#[cfg(feature = "scene")]
|
||||
pub use crate::scene::{Scene, SceneSpawner};
|
||||
#[cfg(feature = "sprite")]
|
||||
pub use crate::sprite::{ColorMaterial, Rect, Sprite, entity::SpriteEntity};
|
||||
#[cfg(feature = "text")]
|
||||
pub use crate::text::Font;
|
||||
#[cfg(feature = "transform")]
|
||||
|
@ -40,15 +41,13 @@ pub use crate::transform::prelude::*;
|
|||
#[cfg(feature = "type_registry")]
|
||||
pub use crate::type_registry::RegisterType;
|
||||
#[cfg(feature = "ui")]
|
||||
pub use crate::ui::{
|
||||
entity::*, widget::Label, Anchors, ColorMaterial, Margins, Node, Rect, Sprite,
|
||||
};
|
||||
pub use crate::ui::{entity::*, widget::Label, Anchors, Margins, Node};
|
||||
#[cfg(feature = "window")]
|
||||
pub use crate::window::{Window, WindowDescriptor, WindowPlugin, Windows};
|
||||
pub use crate::{
|
||||
app::{
|
||||
schedule_runner::ScheduleRunnerPlugin, stage, App, AppBuilder, AppPlugin, EntityArchetype,
|
||||
EventReader, Events, GetEventReader, System,
|
||||
EventReader, Events, FromResources, GetEventReader, System,
|
||||
},
|
||||
math::{self, Mat3, Mat4, Quat, Vec2, Vec3, Vec4},
|
||||
AddDefaultPlugins,
|
||||
|
@ -64,7 +63,7 @@ pub use legion::{
|
|||
bit_set::BitSet,
|
||||
resource::{ResourceSet, Resources},
|
||||
schedule::{Executor, Runnable, Schedulable, Schedule},
|
||||
IntoSystem, Res, ResMut, SubWorld, SystemBuilder, Query
|
||||
IntoSystem, Query, Res, ResMut, SubWorld, SystemBuilder,
|
||||
},
|
||||
world::{Universe, World},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue