port ui over to new render graph
This commit is contained in:
parent
be1a878943
commit
88ecc9ed43
@ -20,7 +20,7 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
|||||||
fn insert(self, world: &mut World) -> Entity {
|
fn insert(self, world: &mut World) -> Entity {
|
||||||
*world.insert((), vec![(
|
*world.insert((), vec![(
|
||||||
#(self.#field_name),*
|
#(self.#field_name),*
|
||||||
)]).first().unwrap()
|
,)]).first().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
173
examples/ui_new.rs
Normal file
173
examples/ui_new.rs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy::render::render_graph_2::{StandardMaterial, ShaderUniforms};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(world: &mut World) {
|
||||||
|
let cube = Mesh::load(MeshType::Cube);
|
||||||
|
let cube_handle = {
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
|
mesh_storage.add(cube)
|
||||||
|
};
|
||||||
|
|
||||||
|
world.build()
|
||||||
|
// cube
|
||||||
|
.add_archetype(NewMeshEntity {
|
||||||
|
mesh: cube_handle.clone(),
|
||||||
|
material: StandardMaterial {
|
||||||
|
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
||||||
|
},
|
||||||
|
shader_uniforms: ShaderUniforms::new(),
|
||||||
|
local_to_world: LocalToWorld::identity(),
|
||||||
|
translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
|
})
|
||||||
|
// light
|
||||||
|
.add_archetype(LightEntity {
|
||||||
|
light: Light {
|
||||||
|
color: wgpu::Color {
|
||||||
|
r: 0.8,
|
||||||
|
g: 0.8,
|
||||||
|
b: 0.5,
|
||||||
|
a: 1.0,
|
||||||
|
},
|
||||||
|
fov: f32::to_radians(60.0),
|
||||||
|
depth: 0.1..50.0,
|
||||||
|
target_view: None,
|
||||||
|
},
|
||||||
|
local_to_world: LocalToWorld::identity(),
|
||||||
|
translation: Translation::new(4.0, -4.0, 5.0),
|
||||||
|
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
|
})
|
||||||
|
// 3d camera
|
||||||
|
.add_archetype(CameraEntity {
|
||||||
|
camera: Camera::new(CameraType::Projection {
|
||||||
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
near: 1.0,
|
||||||
|
far: 1000.0,
|
||||||
|
aspect_ratio: 1.0,
|
||||||
|
}),
|
||||||
|
active_camera: ActiveCamera,
|
||||||
|
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||||
|
Vec3::new(3.0, 8.0, 5.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 0.0, 1.0),
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
// 2d camera
|
||||||
|
.add_archetype(Camera2dEntity {
|
||||||
|
camera: Camera::new(CameraType::Orthographic {
|
||||||
|
left: 0.0,
|
||||||
|
right: 0.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
top: 0.0,
|
||||||
|
near: 0.0,
|
||||||
|
far: 1.0,
|
||||||
|
}),
|
||||||
|
active_camera_2d: ActiveCamera2d,
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
// bottom left anchor with vertical fill
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(0.0, 0.0),
|
||||||
|
Anchors::new(0.0, 0.0, 0.0, 1.0),
|
||||||
|
Margins::new(10.0, 200.0, 10.0, 10.0),
|
||||||
|
math::vec4(0.1, 0.1, 0.1, 1.0),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
|
||||||
|
// top right anchor with vertical fill
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(0.0, 0.0),
|
||||||
|
Anchors::new(1.0, 1.0, 0.0, 1.0),
|
||||||
|
Margins::new(10.0, 100.0, 50.0, 100.0),
|
||||||
|
math::vec4(0.1, 0.1, 0.1, 1.0),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
|
||||||
|
// render order test: reddest in the back, whitest in the front
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(75.0, 75.0),
|
||||||
|
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||||
|
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||||
|
math::vec4(1.0, 0.1, 0.1, 1.0),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(50.0, 50.0),
|
||||||
|
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||||
|
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||||
|
math::vec4(1.0, 0.3, 0.3, 1.0),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(100.0, 100.0),
|
||||||
|
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||||
|
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||||
|
math::vec4(1.0, 0.5, 0.5, 1.0),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(150.0, 150.0),
|
||||||
|
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||||
|
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||||
|
math::vec4(1.0, 0.7, 0.7, 1.0),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
|
||||||
|
// parenting
|
||||||
|
let parent = *world
|
||||||
|
.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(300.0, 300.0),
|
||||||
|
Anchors::new(0.0, 0.0, 0.0, 0.0),
|
||||||
|
Margins::new(0.0, 200.0, 0.0, 200.0),
|
||||||
|
math::vec4(0.1, 0.1, 1.0, 1.0),
|
||||||
|
),)],
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(
|
||||||
|
Node::new(
|
||||||
|
math::vec2(0.0, 0.0),
|
||||||
|
Anchors::new(0.0, 1.0, 0.0, 1.0),
|
||||||
|
Margins::new(20.0, 20.0, 20.0, 20.0),
|
||||||
|
math::vec4(0.6, 0.6, 1.0, 1.0),
|
||||||
|
),
|
||||||
|
Parent(parent),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
|
||||||
|
// alpha test
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(Node::new(
|
||||||
|
math::vec2(200.0, 200.0),
|
||||||
|
Anchors::new(0.5, 0.5, 0.5, 0.5),
|
||||||
|
Margins::new(0.0, 100.0, 0.0, 100.0),
|
||||||
|
math::vec4(1.0, 0.9, 0.9, 0.4),
|
||||||
|
),)],
|
||||||
|
);
|
||||||
|
}
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
core::Time,
|
core::Time,
|
||||||
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
||||||
render::render_graph_2,
|
render::render_graph_2,
|
||||||
render::render_graph_2::{pipelines::*, passes::*, wgpu_renderer::WgpuRenderer, resource_provider::{CameraResourceProvider, LightResourceProvider}, UniformResourceProvider, StandardMaterial},
|
render::render_graph_2::{pipelines::*, passes::*, wgpu_renderer::WgpuRenderer, resource_providers::*, UniformResourceProvider, StandardMaterial},
|
||||||
render::{passes::*, *},
|
render::{passes::*, *},
|
||||||
plugin::load_plugin,
|
plugin::load_plugin,
|
||||||
ui,
|
ui,
|
||||||
@ -175,11 +175,14 @@ impl AppBuilder {
|
|||||||
self.render_graph_builder = self
|
self.render_graph_builder = self
|
||||||
.render_graph_builder
|
.render_graph_builder
|
||||||
.add_resource_provider(Box::new(CameraResourceProvider))
|
.add_resource_provider(Box::new(CameraResourceProvider))
|
||||||
|
.add_resource_provider(Box::new(Camera2dResourceProvider))
|
||||||
.add_resource_provider(Box::new(LightResourceProvider::new(10)))
|
.add_resource_provider(Box::new(LightResourceProvider::new(10)))
|
||||||
|
.add_resource_provider(Box::new(UiResourceProvider::new()))
|
||||||
.add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new()))
|
.add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new()))
|
||||||
.add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new()))
|
.add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new()))
|
||||||
.add_forward_pass()
|
.add_forward_pass()
|
||||||
.add_forward_pipeline();
|
.add_forward_pipeline()
|
||||||
|
.add_ui_pipeline();
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -32,4 +32,15 @@ pub struct CameraEntity {
|
|||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
pub active_camera: ActiveCamera,
|
pub active_camera: ActiveCamera,
|
||||||
pub local_to_world: LocalToWorld,
|
pub local_to_world: LocalToWorld,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(EntityArchetype)]
|
||||||
|
pub struct Camera2dEntity {
|
||||||
|
pub camera: Camera,
|
||||||
|
pub active_camera_2d: ActiveCamera2d,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(EntityArchetype)]
|
||||||
|
pub struct UiEntity {
|
||||||
|
pub node: Node,
|
||||||
}
|
}
|
@ -177,54 +177,55 @@ impl Pipeline for UiPipeline {
|
|||||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||||
|
|
||||||
self.pipeline = Some(render_graph.device.create_render_pipeline(
|
let pipedesc = wgpu::RenderPipelineDescriptor {
|
||||||
&wgpu::RenderPipelineDescriptor {
|
layout: &pipeline_layout,
|
||||||
layout: &pipeline_layout,
|
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
module: &vs_module,
|
||||||
module: &vs_module,
|
entry_point: "main",
|
||||||
entry_point: "main",
|
|
||||||
},
|
|
||||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
|
||||||
module: &fs_module,
|
|
||||||
entry_point: "main",
|
|
||||||
}),
|
|
||||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
|
||||||
front_face: wgpu::FrontFace::Ccw,
|
|
||||||
cull_mode: wgpu::CullMode::None,
|
|
||||||
depth_bias: 0,
|
|
||||||
depth_bias_slope_scale: 0.0,
|
|
||||||
depth_bias_clamp: 0.0,
|
|
||||||
}),
|
|
||||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
|
||||||
color_states: &[wgpu::ColorStateDescriptor {
|
|
||||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
|
||||||
color_blend: wgpu::BlendDescriptor {
|
|
||||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
|
||||||
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
|
||||||
operation: wgpu::BlendOperation::Add,
|
|
||||||
},
|
|
||||||
alpha_blend: wgpu::BlendDescriptor {
|
|
||||||
src_factor: wgpu::BlendFactor::One,
|
|
||||||
dst_factor: wgpu::BlendFactor::One,
|
|
||||||
operation: wgpu::BlendOperation::Add,
|
|
||||||
},
|
|
||||||
write_mask: wgpu::ColorWrite::ALL,
|
|
||||||
}],
|
|
||||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
|
||||||
format: self.depth_format,
|
|
||||||
depth_write_enabled: false,
|
|
||||||
depth_compare: wgpu::CompareFunction::Always,
|
|
||||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
|
||||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
|
||||||
stencil_read_mask: 0,
|
|
||||||
stencil_write_mask: 0,
|
|
||||||
}),
|
|
||||||
index_format: wgpu::IndexFormat::Uint16,
|
|
||||||
vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor],
|
|
||||||
sample_count: self.msaa_samples as u32,
|
|
||||||
sample_mask: !0,
|
|
||||||
alpha_to_coverage_enabled: false,
|
|
||||||
},
|
},
|
||||||
|
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||||
|
module: &fs_module,
|
||||||
|
entry_point: "main",
|
||||||
|
}),
|
||||||
|
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||||
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
|
cull_mode: wgpu::CullMode::None,
|
||||||
|
depth_bias: 0,
|
||||||
|
depth_bias_slope_scale: 0.0,
|
||||||
|
depth_bias_clamp: 0.0,
|
||||||
|
}),
|
||||||
|
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||||
|
color_states: &[wgpu::ColorStateDescriptor {
|
||||||
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
|
color_blend: wgpu::BlendDescriptor {
|
||||||
|
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||||
|
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
alpha_blend: wgpu::BlendDescriptor {
|
||||||
|
src_factor: wgpu::BlendFactor::One,
|
||||||
|
dst_factor: wgpu::BlendFactor::One,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
write_mask: wgpu::ColorWrite::ALL,
|
||||||
|
}],
|
||||||
|
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||||
|
format: self.depth_format,
|
||||||
|
depth_write_enabled: false,
|
||||||
|
depth_compare: wgpu::CompareFunction::Always,
|
||||||
|
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||||
|
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||||
|
stencil_read_mask: 0,
|
||||||
|
stencil_write_mask: 0,
|
||||||
|
}),
|
||||||
|
index_format: wgpu::IndexFormat::Uint16,
|
||||||
|
vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor],
|
||||||
|
sample_count: self.msaa_samples as u32,
|
||||||
|
sample_mask: !0,
|
||||||
|
alpha_to_coverage_enabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.pipeline = Some(render_graph.device.create_render_pipeline(&pipedesc
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::resource_name;
|
||||||
|
use super::ResourceInfo;
|
||||||
use zerocopy::AsBytes;
|
use zerocopy::AsBytes;
|
||||||
|
|
||||||
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
|
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
|
||||||
@ -60,3 +62,46 @@ pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
|||||||
renderer.remove_buffer(MESH_VERTEX_BUFFER_NAME);
|
renderer.remove_buffer(MESH_VERTEX_BUFFER_NAME);
|
||||||
renderer.remove_buffer(MESH_INDEX_BUFFER_NAME);
|
renderer.remove_buffer(MESH_INDEX_BUFFER_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ui_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
|
// NOTE: this is ugly and borrowing is stupid
|
||||||
|
let result = {
|
||||||
|
let renderer = render_pass.get_renderer();
|
||||||
|
let result = if let Some(ResourceInfo::InstanceBuffer { count, mesh_id, .. }) =
|
||||||
|
renderer.get_resource_info(resource_name::buffer::UI_INSTANCES)
|
||||||
|
{
|
||||||
|
Some((*count, *mesh_id))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((instance_count, mesh_id)) = result {
|
||||||
|
if let Some(mesh_asset) = mesh_storage.get(mesh_id) {
|
||||||
|
renderer.create_buffer_with_data(
|
||||||
|
MESH_VERTEX_BUFFER_NAME,
|
||||||
|
mesh_asset.vertices.as_bytes(),
|
||||||
|
wgpu::BufferUsage::VERTEX,
|
||||||
|
);
|
||||||
|
renderer.create_buffer_with_data(
|
||||||
|
MESH_INDEX_BUFFER_NAME,
|
||||||
|
mesh_asset.indices.as_bytes(),
|
||||||
|
wgpu::BufferUsage::INDEX,
|
||||||
|
);
|
||||||
|
Some((instance_count, mesh_asset.indices.len()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
if let Some((instance_count, indices_length)) = result {
|
||||||
|
render_pass.setup_bind_groups(None);
|
||||||
|
render_pass.set_index_buffer(MESH_INDEX_BUFFER_NAME, 0);
|
||||||
|
render_pass.set_vertex_buffer(0, MESH_VERTEX_BUFFER_NAME, 0);
|
||||||
|
render_pass.set_vertex_buffer(1, resource_name::buffer::UI_INSTANCES, 0);
|
||||||
|
render_pass.draw_indexed(0..indices_length as u32, 0, 0..(instance_count as u32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ pub mod pipelines;
|
|||||||
pub mod resource_name;
|
pub mod resource_name;
|
||||||
pub mod wgpu_renderer;
|
pub mod wgpu_renderer;
|
||||||
pub mod resource_provider;
|
pub mod resource_provider;
|
||||||
|
pub mod resource_providers;
|
||||||
pub mod passes;
|
pub mod passes;
|
||||||
mod resource;
|
mod resource;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::render::render_graph_2::{
|
use crate::render::render_graph_2::{
|
||||||
resource_name, PassDescriptor, RenderGraphBuilder, RenderPassColorAttachmentDescriptor,
|
resource_name, PassDescriptor, RenderGraphBuilder, RenderPassColorAttachmentDescriptor,
|
||||||
RenderPassDepthStencilAttachmentDescriptor, TextureDescriptor, TextureDimension,
|
RenderPassDepthStencilAttachmentDescriptor, TextureDescriptor, TextureDimension,
|
||||||
FrameTexture,
|
resource_providers::FrameTextureResourceProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ForwardPassBuilder {
|
pub trait ForwardPassBuilder {
|
||||||
@ -10,7 +10,7 @@ pub trait ForwardPassBuilder {
|
|||||||
|
|
||||||
impl ForwardPassBuilder for RenderGraphBuilder {
|
impl ForwardPassBuilder for RenderGraphBuilder {
|
||||||
fn add_forward_pass(self) -> Self {
|
fn add_forward_pass(self) -> Self {
|
||||||
self.add_resource_provider(Box::new(FrameTexture::new(resource_name::texture::DEPTH, TextureDescriptor {
|
self.add_resource_provider(Box::new(FrameTextureResourceProvider::new(resource_name::texture::DEPTH, TextureDescriptor {
|
||||||
size: wgpu::Extent3d {
|
size: wgpu::Extent3d {
|
||||||
depth: 1,
|
depth: 1,
|
||||||
width: 1,
|
width: 1,
|
||||||
|
@ -87,14 +87,12 @@ impl PipelineDescriptor {
|
|||||||
|
|
||||||
pub struct PipelineBuilder {
|
pub struct PipelineBuilder {
|
||||||
pipeline: PipelineDescriptor,
|
pipeline: PipelineDescriptor,
|
||||||
vertex_buffer_descriptor_offset: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineBuilder {
|
impl PipelineBuilder {
|
||||||
pub fn new(vertex_shader: Shader) -> Self {
|
pub fn new(vertex_shader: Shader) -> Self {
|
||||||
PipelineBuilder {
|
PipelineBuilder {
|
||||||
pipeline: PipelineDescriptor::new(vertex_shader),
|
pipeline: PipelineDescriptor::new(vertex_shader),
|
||||||
vertex_buffer_descriptor_offset: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,16 +128,8 @@ impl PipelineBuilder {
|
|||||||
|
|
||||||
pub fn add_vertex_buffer_descriptor(
|
pub fn add_vertex_buffer_descriptor(
|
||||||
mut self,
|
mut self,
|
||||||
mut vertex_buffer_descriptor: VertexBufferDescriptor,
|
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut offset = 0;
|
|
||||||
for attribute in vertex_buffer_descriptor.attributes.iter_mut() {
|
|
||||||
offset += attribute.offset;
|
|
||||||
attribute.offset += self.vertex_buffer_descriptor_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.vertex_buffer_descriptor_offset += offset;
|
|
||||||
|
|
||||||
self.pipeline
|
self.pipeline
|
||||||
.vertex_buffer_descriptors
|
.vertex_buffer_descriptors
|
||||||
.push(vertex_buffer_descriptor);
|
.push(vertex_buffer_descriptor);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
mod forward;
|
mod forward;
|
||||||
mod forward_flat;
|
mod forward_flat;
|
||||||
|
mod ui;
|
||||||
|
|
||||||
pub use forward::*;
|
pub use forward::*;
|
||||||
pub use forward_flat::*;
|
pub use forward_flat::*;
|
||||||
|
pub use ui::*;
|
108
src/render/render_graph_2/pipelines/ui/mod.rs
Normal file
108
src/render/render_graph_2/pipelines/ui/mod.rs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
use crate::render::{
|
||||||
|
Vertex,
|
||||||
|
{
|
||||||
|
render_graph_2::{
|
||||||
|
ui_draw_target, pipeline_layout::*, PipelineDescriptor,
|
||||||
|
RenderGraphBuilder,
|
||||||
|
},
|
||||||
|
shader::{Shader, ShaderStage},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use crate::render::render_graph_2::VertexBufferDescriptor;
|
||||||
|
use crate::render::render_graph_2::resource_providers::RectData;
|
||||||
|
pub trait UiPipelineBuilder {
|
||||||
|
fn add_ui_pipeline(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiPipelineBuilder for RenderGraphBuilder {
|
||||||
|
fn add_ui_pipeline(self) -> Self {
|
||||||
|
self.add_pipeline(
|
||||||
|
"ui",
|
||||||
|
PipelineDescriptor::build(Shader::from_glsl(
|
||||||
|
include_str!("ui.vert"),
|
||||||
|
ShaderStage::Vertex,
|
||||||
|
))
|
||||||
|
.with_fragment_shader(Shader::from_glsl(
|
||||||
|
include_str!("ui.frag"),
|
||||||
|
ShaderStage::Fragment,
|
||||||
|
))
|
||||||
|
.add_bind_group(BindGroup::new(
|
||||||
|
vec![
|
||||||
|
Binding {
|
||||||
|
name: "Camera2d".to_string(),
|
||||||
|
bind_type: BindType::Uniform {
|
||||||
|
dynamic: false,
|
||||||
|
properties: vec![
|
||||||
|
UniformProperty {
|
||||||
|
name: "ViewProj".to_string(),
|
||||||
|
property_type: UniformPropertyType::Mat4,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
))
|
||||||
|
.with_rasterization_state(wgpu::RasterizationStateDescriptor {
|
||||||
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
|
cull_mode: wgpu::CullMode::None,
|
||||||
|
depth_bias: 0,
|
||||||
|
depth_bias_slope_scale: 0.0,
|
||||||
|
depth_bias_clamp: 0.0,
|
||||||
|
})
|
||||||
|
.with_depth_stencil_state(wgpu::DepthStencilStateDescriptor {
|
||||||
|
format: wgpu::TextureFormat::Depth32Float,
|
||||||
|
depth_write_enabled: false,
|
||||||
|
depth_compare: wgpu::CompareFunction::Always,
|
||||||
|
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||||
|
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||||
|
stencil_read_mask: 0,
|
||||||
|
stencil_write_mask: 0,
|
||||||
|
})
|
||||||
|
.add_color_state(wgpu::ColorStateDescriptor {
|
||||||
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
|
color_blend: wgpu::BlendDescriptor {
|
||||||
|
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||||
|
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
alpha_blend: wgpu::BlendDescriptor {
|
||||||
|
src_factor: wgpu::BlendFactor::One,
|
||||||
|
dst_factor: wgpu::BlendFactor::One,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
write_mask: wgpu::ColorWrite::ALL,
|
||||||
|
})
|
||||||
|
.add_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
||||||
|
.add_vertex_buffer_descriptor(
|
||||||
|
VertexBufferDescriptor {
|
||||||
|
stride: std::mem::size_of::<RectData>() as u64,
|
||||||
|
step_mode: wgpu::InputStepMode::Instance,
|
||||||
|
attributes: vec![
|
||||||
|
wgpu::VertexAttributeDescriptor {
|
||||||
|
format: wgpu::VertexFormat::Float2,
|
||||||
|
offset: 0,
|
||||||
|
shader_location: 3,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttributeDescriptor {
|
||||||
|
format: wgpu::VertexFormat::Float2,
|
||||||
|
offset: 2 * 4,
|
||||||
|
shader_location: 4,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttributeDescriptor {
|
||||||
|
format: wgpu::VertexFormat::Float4,
|
||||||
|
offset: 4 * 4,
|
||||||
|
shader_location: 5,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttributeDescriptor {
|
||||||
|
format: wgpu::VertexFormat::Float,
|
||||||
|
offset: 8 * 4,
|
||||||
|
shader_location: 6,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.add_draw_target(ui_draw_target)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
9
src/render/render_graph_2/pipelines/ui/ui.frag
Normal file
9
src/render/render_graph_2/pipelines/ui/ui.frag
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 v_Color;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 o_Target;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
o_Target = v_Color;
|
||||||
|
}
|
25
src/render/render_graph_2/pipelines/ui/ui.vert
Normal file
25
src/render/render_graph_2/pipelines/ui/ui.vert
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
// vertex attributes
|
||||||
|
layout(location = 0) in vec4 a_Pos;
|
||||||
|
layout(location = 1) in vec4 a_Normal;
|
||||||
|
layout(location = 2) in vec2 a_Uv;
|
||||||
|
|
||||||
|
// instanced attributes (RectData)
|
||||||
|
layout (location = 3) in vec2 a_RectPosition;
|
||||||
|
layout (location = 4) in vec2 a_RectSize;
|
||||||
|
layout (location = 5) in vec4 a_RectColor;
|
||||||
|
layout (location = 6) in float a_RectZIndex;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 v_Color;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform Camera2d {
|
||||||
|
mat4 ViewProj;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
v_Color = a_RectColor;
|
||||||
|
vec4 position = a_Pos * vec4(a_RectSize, 0.0, 1.0);
|
||||||
|
position = position + vec4(a_RectPosition + a_RectSize / 2.0, -a_RectZIndex, 0.0);
|
||||||
|
gl_Position = ViewProj * position;
|
||||||
|
}
|
@ -27,6 +27,8 @@ pub trait Renderer {
|
|||||||
) -> Option<&mut DynamicUniformBufferInfo>;
|
) -> Option<&mut DynamicUniformBufferInfo>;
|
||||||
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo);
|
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo);
|
||||||
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage);
|
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage);
|
||||||
|
fn create_instance_buffer(&mut self, name: &str, mesh_id: usize, size: usize, count: usize, buffer_usage: wgpu::BufferUsage);
|
||||||
|
fn create_instance_buffer_with_data(&mut self, name: &str, mesh_id: usize, data: &[u8], size: usize, count: usize, buffer_usage: wgpu::BufferUsage);
|
||||||
fn create_buffer_mapped(
|
fn create_buffer_mapped(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -8,4 +8,11 @@ pub enum ResourceInfo {
|
|||||||
buffer_usage: wgpu::BufferUsage,
|
buffer_usage: wgpu::BufferUsage,
|
||||||
// pub layout: Option<
|
// pub layout: Option<
|
||||||
},
|
},
|
||||||
|
InstanceBuffer {
|
||||||
|
size: usize,
|
||||||
|
count: usize,
|
||||||
|
buffer_usage: wgpu::BufferUsage,
|
||||||
|
mesh_id: usize,
|
||||||
|
// pub layout: Option<
|
||||||
|
},
|
||||||
}
|
}
|
@ -5,5 +5,10 @@ pub mod texture {
|
|||||||
|
|
||||||
pub mod uniform {
|
pub mod uniform {
|
||||||
pub const CAMERA: &str = "Camera";
|
pub const CAMERA: &str = "Camera";
|
||||||
|
pub const CAMERA2D: &str = "Camera2d";
|
||||||
pub const LIGHTS: &str = "Lights";
|
pub const LIGHTS: &str = "Lights";
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod buffer {
|
||||||
|
pub const UI_INSTANCES: &str = "UiInstances";
|
||||||
}
|
}
|
@ -1,171 +1,8 @@
|
|||||||
use crate::{render::{
|
use crate::render::render_graph_2::Renderer;
|
||||||
render_graph_2::{resource_name, Renderer, TextureDescriptor},
|
|
||||||
ActiveCamera, Camera, Light, LightRaw,
|
|
||||||
}, transform::prelude::Translation};
|
|
||||||
use bevy_transform::prelude::LocalToWorld;
|
|
||||||
use legion::prelude::*;
|
use legion::prelude::*;
|
||||||
use zerocopy::AsBytes;
|
|
||||||
|
|
||||||
pub trait ResourceProvider {
|
pub trait ResourceProvider {
|
||||||
fn initialize(&mut self, renderer: &mut dyn Renderer, world: &mut World);
|
fn initialize(&mut self, renderer: &mut dyn Renderer, world: &mut World);
|
||||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World);
|
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World);
|
||||||
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32);
|
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32);
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CameraResourceProvider;
|
|
||||||
|
|
||||||
impl ResourceProvider for CameraResourceProvider {
|
|
||||||
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
|
||||||
renderer.create_buffer(
|
|
||||||
resource_name::uniform::CAMERA,
|
|
||||||
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
|
|
||||||
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
|
||||||
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
|
||||||
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
|
||||||
for (mut camera, local_to_world, _) in
|
|
||||||
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
|
|
||||||
{
|
|
||||||
camera.update(width, height);
|
|
||||||
let camera_matrix: [[f32; 4]; 4] =
|
|
||||||
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
|
|
||||||
|
|
||||||
renderer.create_buffer_mapped(
|
|
||||||
"camera_tmp",
|
|
||||||
matrix_size,
|
|
||||||
wgpu::BufferUsage::COPY_SRC,
|
|
||||||
&mut |data| {
|
|
||||||
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
renderer.copy_buffer_to_buffer(
|
|
||||||
"camera_tmp",
|
|
||||||
0,
|
|
||||||
resource_name::uniform::CAMERA,
|
|
||||||
0,
|
|
||||||
matrix_size as u64,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LightResourceProvider {
|
|
||||||
pub lights_are_dirty: bool,
|
|
||||||
pub max_lights: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy, AsBytes)]
|
|
||||||
pub struct LightCount {
|
|
||||||
pub num_lights: [u32; 4],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LightResourceProvider {
|
|
||||||
pub fn new(max_lights: usize) -> Self {
|
|
||||||
LightResourceProvider {
|
|
||||||
lights_are_dirty: true,
|
|
||||||
max_lights: max_lights,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ResourceProvider for LightResourceProvider {
|
|
||||||
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
|
||||||
let light_uniform_size =
|
|
||||||
(std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
|
|
||||||
|
|
||||||
renderer.create_buffer(
|
|
||||||
resource_name::uniform::LIGHTS,
|
|
||||||
light_uniform_size,
|
|
||||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::COPY_DST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
|
||||||
if self.lights_are_dirty {
|
|
||||||
let light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
|
|
||||||
let light_count = light_query.iter(world).count();
|
|
||||||
|
|
||||||
if light_count == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.lights_are_dirty = false;
|
|
||||||
let size = std::mem::size_of::<LightRaw>();
|
|
||||||
let total_size = size * light_count;
|
|
||||||
let light_count_size = std::mem::size_of::<LightCount>();
|
|
||||||
renderer
|
|
||||||
.create_buffer_mapped("LIGHT_TMP", total_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
|
|
||||||
for ((light, local_to_world, translation), slot) in light_query
|
|
||||||
.iter(world)
|
|
||||||
.zip(data.chunks_exact_mut(size))
|
|
||||||
{
|
|
||||||
slot.copy_from_slice(
|
|
||||||
LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
renderer
|
|
||||||
.create_buffer_mapped("LIGHT_COUNT_TMP", light_count_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
|
|
||||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
|
||||||
});
|
|
||||||
|
|
||||||
renderer.copy_buffer_to_buffer(
|
|
||||||
"LIGHT_COUNT_TMP",
|
|
||||||
0,
|
|
||||||
resource_name::uniform::LIGHTS,
|
|
||||||
0,
|
|
||||||
light_count_size as wgpu::BufferAddress,
|
|
||||||
);
|
|
||||||
|
|
||||||
renderer.copy_buffer_to_buffer(
|
|
||||||
"LIGHT_TMP",
|
|
||||||
0,
|
|
||||||
resource_name::uniform::LIGHTS,
|
|
||||||
light_count_size as u64,
|
|
||||||
total_size as wgpu::BufferAddress,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FrameTexture {
|
|
||||||
pub name: String,
|
|
||||||
pub descriptor: TextureDescriptor,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FrameTexture {
|
|
||||||
pub fn new(name: &str, descriptor: TextureDescriptor) -> Self {
|
|
||||||
FrameTexture {
|
|
||||||
name: name.to_string(),
|
|
||||||
descriptor,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, renderer: &mut dyn Renderer, world: &World) {
|
|
||||||
let window = world.resources.get::<winit::window::Window>().unwrap();
|
|
||||||
let window_size = window.inner_size();
|
|
||||||
self.descriptor.size.width = window_size.width;
|
|
||||||
self.descriptor.size.height = window_size.height;
|
|
||||||
renderer.create_texture(&self.name, &self.descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ResourceProvider for FrameTexture {
|
|
||||||
fn initialize(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
|
||||||
self.update(renderer, world);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
|
||||||
self.update(renderer, world);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
use crate::{render::{
|
||||||
|
render_graph_2::{resource_name, Renderer},
|
||||||
|
ActiveCamera2d, Camera,
|
||||||
|
}};
|
||||||
|
use legion::prelude::*;
|
||||||
|
use zerocopy::AsBytes;
|
||||||
|
use crate::render::render_graph_2::ResourceProvider;
|
||||||
|
|
||||||
|
pub struct Camera2dResourceProvider;
|
||||||
|
|
||||||
|
impl ResourceProvider for Camera2dResourceProvider {
|
||||||
|
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
||||||
|
renderer.create_buffer(
|
||||||
|
resource_name::uniform::CAMERA2D,
|
||||||
|
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
|
||||||
|
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||||
|
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
||||||
|
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||||
|
for (mut camera, _) in
|
||||||
|
<(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world)
|
||||||
|
{
|
||||||
|
camera.update(width, height);
|
||||||
|
let camera_matrix: [[f32; 4]; 4] =
|
||||||
|
camera.view_matrix.to_cols_array_2d();
|
||||||
|
|
||||||
|
renderer.create_buffer_mapped(
|
||||||
|
"camera2d_tmp",
|
||||||
|
matrix_size,
|
||||||
|
wgpu::BufferUsage::COPY_SRC,
|
||||||
|
&mut |data| {
|
||||||
|
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
renderer.copy_buffer_to_buffer(
|
||||||
|
"camera2d_tmp",
|
||||||
|
0,
|
||||||
|
resource_name::uniform::CAMERA2D,
|
||||||
|
0,
|
||||||
|
matrix_size as u64,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
use crate::{render::{
|
||||||
|
render_graph_2::{resource_name, Renderer},
|
||||||
|
ActiveCamera, Camera,
|
||||||
|
}};
|
||||||
|
use bevy_transform::prelude::LocalToWorld;
|
||||||
|
use legion::prelude::*;
|
||||||
|
use zerocopy::AsBytes;
|
||||||
|
use crate::render::render_graph_2::ResourceProvider;
|
||||||
|
|
||||||
|
pub struct CameraResourceProvider;
|
||||||
|
|
||||||
|
impl ResourceProvider for CameraResourceProvider {
|
||||||
|
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
||||||
|
renderer.create_buffer(
|
||||||
|
resource_name::uniform::CAMERA,
|
||||||
|
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
|
||||||
|
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||||
|
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
||||||
|
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||||
|
for (mut camera, local_to_world, _) in
|
||||||
|
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
|
||||||
|
{
|
||||||
|
camera.update(width, height);
|
||||||
|
let camera_matrix: [[f32; 4]; 4] =
|
||||||
|
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
|
||||||
|
|
||||||
|
renderer.create_buffer_mapped(
|
||||||
|
"camera_tmp",
|
||||||
|
matrix_size,
|
||||||
|
wgpu::BufferUsage::COPY_SRC,
|
||||||
|
&mut |data| {
|
||||||
|
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
renderer.copy_buffer_to_buffer(
|
||||||
|
"camera_tmp",
|
||||||
|
0,
|
||||||
|
resource_name::uniform::CAMERA,
|
||||||
|
0,
|
||||||
|
matrix_size as u64,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
use crate::prelude::World;
|
||||||
|
use crate::render::render_graph_2::Renderer;
|
||||||
|
use crate::render::render_graph_2::ResourceProvider;
|
||||||
|
use crate::render::render_graph_2::TextureDescriptor;
|
||||||
|
|
||||||
|
pub struct FrameTextureResourceProvider {
|
||||||
|
pub name: String,
|
||||||
|
pub descriptor: TextureDescriptor,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FrameTextureResourceProvider {
|
||||||
|
pub fn new(name: &str, descriptor: TextureDescriptor) -> Self {
|
||||||
|
FrameTextureResourceProvider {
|
||||||
|
name: name.to_string(),
|
||||||
|
descriptor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, renderer: &mut dyn Renderer, world: &World) {
|
||||||
|
let window = world.resources.get::<winit::window::Window>().unwrap();
|
||||||
|
let window_size = window.inner_size();
|
||||||
|
self.descriptor.size.width = window_size.width;
|
||||||
|
self.descriptor.size.height = window_size.height;
|
||||||
|
renderer.create_texture(&self.name, &self.descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceProvider for FrameTextureResourceProvider {
|
||||||
|
fn initialize(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
||||||
|
self.update(renderer, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||||
|
|
||||||
|
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, _width: u32, _height: u32) {
|
||||||
|
self.update(renderer, world);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
use zerocopy::AsBytes;
|
||||||
|
use legion::prelude::*;
|
||||||
|
use crate::render::render_graph_2::ResourceProvider;
|
||||||
|
use crate::render::render_graph_2::resource_name;
|
||||||
|
use crate::render::render_graph_2::Renderer;
|
||||||
|
use crate::render::{Light, LightRaw};
|
||||||
|
use bevy_transform::prelude::{LocalToWorld, Translation};
|
||||||
|
|
||||||
|
pub struct LightResourceProvider {
|
||||||
|
pub lights_are_dirty: bool,
|
||||||
|
pub max_lights: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, AsBytes)]
|
||||||
|
pub struct LightCount {
|
||||||
|
pub num_lights: [u32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LightResourceProvider {
|
||||||
|
pub fn new(max_lights: usize) -> Self {
|
||||||
|
LightResourceProvider {
|
||||||
|
lights_are_dirty: true,
|
||||||
|
max_lights: max_lights,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceProvider for LightResourceProvider {
|
||||||
|
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
||||||
|
let light_uniform_size =
|
||||||
|
(std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
|
||||||
|
|
||||||
|
renderer.create_buffer(
|
||||||
|
resource_name::uniform::LIGHTS,
|
||||||
|
light_uniform_size,
|
||||||
|
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::COPY_DST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
||||||
|
if self.lights_are_dirty {
|
||||||
|
let light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
|
||||||
|
let light_count = light_query.iter(world).count();
|
||||||
|
|
||||||
|
if light_count == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.lights_are_dirty = false;
|
||||||
|
let size = std::mem::size_of::<LightRaw>();
|
||||||
|
let total_size = size * light_count;
|
||||||
|
let light_count_size = std::mem::size_of::<LightCount>();
|
||||||
|
renderer
|
||||||
|
.create_buffer_mapped("LIGHT_TMP", total_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
|
||||||
|
for ((light, local_to_world, translation), slot) in light_query
|
||||||
|
.iter(world)
|
||||||
|
.zip(data.chunks_exact_mut(size))
|
||||||
|
{
|
||||||
|
slot.copy_from_slice(
|
||||||
|
LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
renderer
|
||||||
|
.create_buffer_mapped("LIGHT_COUNT_TMP", light_count_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
|
||||||
|
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||||
|
});
|
||||||
|
|
||||||
|
renderer.copy_buffer_to_buffer(
|
||||||
|
"LIGHT_COUNT_TMP",
|
||||||
|
0,
|
||||||
|
resource_name::uniform::LIGHTS,
|
||||||
|
0,
|
||||||
|
light_count_size as wgpu::BufferAddress,
|
||||||
|
);
|
||||||
|
|
||||||
|
renderer.copy_buffer_to_buffer(
|
||||||
|
"LIGHT_TMP",
|
||||||
|
0,
|
||||||
|
resource_name::uniform::LIGHTS,
|
||||||
|
light_count_size as u64,
|
||||||
|
total_size as wgpu::BufferAddress,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize(&mut self, _renderer: &mut dyn Renderer, _world: &mut World, _width: u32, _height: u32) {}
|
||||||
|
}
|
11
src/render/render_graph_2/resource_providers/mod.rs
Normal file
11
src/render/render_graph_2/resource_providers/mod.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
mod ui_resource_provider;
|
||||||
|
mod frame_texture_resource_provider;
|
||||||
|
mod light_resource_provider;
|
||||||
|
mod camera_resource_provider;
|
||||||
|
mod camera2d_resource_provider;
|
||||||
|
|
||||||
|
pub use ui_resource_provider::*;
|
||||||
|
pub use frame_texture_resource_provider::*;
|
||||||
|
pub use light_resource_provider::*;
|
||||||
|
pub use camera_resource_provider::*;
|
||||||
|
pub use camera2d_resource_provider::*;
|
@ -0,0 +1,100 @@
|
|||||||
|
use crate::prelude::Node;
|
||||||
|
use crate::render::render_graph_2::resource_name;
|
||||||
|
use crate::render::render_graph_2::ResourceProvider;
|
||||||
|
use crate::{ecs, render::render_graph_2::Renderer, asset::{Handle, Mesh, Asset, AssetStorage}, math};
|
||||||
|
use bevy_transform::prelude::Parent;
|
||||||
|
use legion::prelude::*;
|
||||||
|
use zerocopy::{AsBytes, FromBytes};
|
||||||
|
use crate::asset::MeshType;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug, AsBytes, FromBytes)]
|
||||||
|
pub struct RectData {
|
||||||
|
pub position: [f32; 2],
|
||||||
|
pub size: [f32; 2],
|
||||||
|
pub color: [f32; 4],
|
||||||
|
pub z_index: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UiResourceProvider {
|
||||||
|
pub quad: Option<Handle<Mesh>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiResourceProvider {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
UiResourceProvider {
|
||||||
|
quad: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, renderer: &mut dyn Renderer, world: &World) {
|
||||||
|
let node_query = <Read<Node>>::query().filter(!component::<Parent>());
|
||||||
|
|
||||||
|
let mut data = Vec::new();
|
||||||
|
if node_query.iter(world).count() > 0 {
|
||||||
|
// TODO: this probably isn't the best way to handle z-ordering
|
||||||
|
let mut z = 0.9999;
|
||||||
|
{
|
||||||
|
let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> =
|
||||||
|
Box::new(|world, entity, _| {
|
||||||
|
let node = world.get_component::<Node>(entity).unwrap();
|
||||||
|
data.push(RectData {
|
||||||
|
position: node.global_position.into(),
|
||||||
|
size: node.size.into(),
|
||||||
|
color: node.color.into(),
|
||||||
|
z_index: z,
|
||||||
|
});
|
||||||
|
|
||||||
|
z -= 0.0001;
|
||||||
|
Some(())
|
||||||
|
});
|
||||||
|
|
||||||
|
for entity in node_query
|
||||||
|
.iter_entities(world)
|
||||||
|
.map(|(entity, _)| entity)
|
||||||
|
.collect::<Vec<Entity>>()
|
||||||
|
{
|
||||||
|
ecs::run_on_hierarchy(world, entity, (), &mut add_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.len() == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = std::mem::size_of::<RectData>();
|
||||||
|
|
||||||
|
let mesh_id = self.quad.as_ref().unwrap().id;
|
||||||
|
|
||||||
|
renderer.create_instance_buffer_with_data(
|
||||||
|
resource_name::buffer::UI_INSTANCES,
|
||||||
|
mesh_id,
|
||||||
|
data.as_bytes(),
|
||||||
|
size,
|
||||||
|
data.len(),
|
||||||
|
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceProvider for UiResourceProvider {
|
||||||
|
fn initialize(&mut self, _renderer: &mut dyn Renderer, world: &mut World) {
|
||||||
|
// self.update(renderer, world);
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
|
let quad = Mesh::load(MeshType::Quad {
|
||||||
|
north_west: math::vec2(-0.5, 0.5),
|
||||||
|
north_east: math::vec2(0.5, 0.5),
|
||||||
|
south_west: math::vec2(-0.5, -0.5),
|
||||||
|
south_east: math::vec2(0.5, -0.5),
|
||||||
|
});
|
||||||
|
self.quad = Some(mesh_storage.add(quad));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
||||||
|
self.update(renderer, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize(&mut self, _renderer: &mut dyn Renderer, _world: &mut World, _width: u32, _height: u32) {
|
||||||
|
}
|
||||||
|
}
|
@ -260,7 +260,7 @@ impl<T> ResourceProvider for UniformResourceProvider<T>
|
|||||||
where
|
where
|
||||||
T: AsUniforms + Send + Sync + 'static,
|
T: AsUniforms + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn initialize(&mut self, renderer: &mut dyn super::Renderer, world: &mut World) {}
|
fn initialize(&mut self, _renderer: &mut dyn super::Renderer, _world: &mut World) {}
|
||||||
|
|
||||||
fn update(&mut self, renderer: &mut dyn super::Renderer, world: &mut World) {
|
fn update(&mut self, renderer: &mut dyn super::Renderer, world: &mut World) {
|
||||||
let query = <Read<T>>::query();
|
let query = <Read<T>>::query();
|
||||||
@ -381,7 +381,7 @@ where
|
|||||||
|
|
||||||
fn resize(
|
fn resize(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &mut dyn super::Renderer,
|
_renderer: &mut dyn super::Renderer,
|
||||||
_world: &mut World,
|
_world: &mut World,
|
||||||
_width: u32,
|
_width: u32,
|
||||||
_height: u32,
|
_height: u32,
|
||||||
|
@ -255,6 +255,7 @@ impl WgpuRenderer {
|
|||||||
// if a uniform resource buffer doesn't exist, create a new empty one
|
// if a uniform resource buffer doesn't exist, create a new empty one
|
||||||
for binding in bind_group.bindings.iter() {
|
for binding in bind_group.bindings.iter() {
|
||||||
if let None = self.resource_info.get(&binding.name) {
|
if let None = self.resource_info.get(&binding.name) {
|
||||||
|
println!("Warning: creating new empty buffer for binding {}", binding.name);
|
||||||
unset_uniforms.push(binding.name.to_string());
|
unset_uniforms.push(binding.name.to_string());
|
||||||
if let BindType::Uniform { .. } = &binding.bind_type {
|
if let BindType::Uniform { .. } = &binding.bind_type {
|
||||||
let size = binding.bind_type.get_uniform_size().unwrap();
|
let size = binding.bind_type.get_uniform_size().unwrap();
|
||||||
@ -584,6 +585,41 @@ impl Renderer for WgpuRenderer {
|
|||||||
self.buffers.insert(name.to_string(), buffer);
|
self.buffers.insert(name.to_string(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_instance_buffer(&mut self, name: &str, mesh_id: usize, size: usize, count: usize, buffer_usage: wgpu::BufferUsage) {
|
||||||
|
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
|
size: (size * count) as u64,
|
||||||
|
usage: buffer_usage,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.add_resource_info(
|
||||||
|
name,
|
||||||
|
ResourceInfo::InstanceBuffer {
|
||||||
|
buffer_usage,
|
||||||
|
size,
|
||||||
|
count,
|
||||||
|
mesh_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.buffers.insert(name.to_string(), buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_instance_buffer_with_data(&mut self, name: &str, mesh_id: usize, data: &[u8], size: usize, count: usize, buffer_usage: wgpu::BufferUsage) {
|
||||||
|
let buffer = self.device.create_buffer_with_data(data, buffer_usage);
|
||||||
|
|
||||||
|
self.add_resource_info(
|
||||||
|
name,
|
||||||
|
ResourceInfo::InstanceBuffer {
|
||||||
|
buffer_usage,
|
||||||
|
size,
|
||||||
|
count,
|
||||||
|
mesh_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.buffers.insert(name.to_string(), buffer);
|
||||||
|
}
|
||||||
|
|
||||||
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo> {
|
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo> {
|
||||||
self.resource_info.get(name)
|
self.resource_info.get(name)
|
||||||
}
|
}
|
||||||
@ -719,6 +755,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: check to see if bind group is already set
|
||||||
self.render_pass.set_bind_group(
|
self.render_pass.set_bind_group(
|
||||||
i as u32,
|
i as u32,
|
||||||
&bind_group_info.bind_group,
|
&bind_group_info.bind_group,
|
||||||
|
Loading…
Reference in New Issue
Block a user