mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
more graph work
This commit is contained in:
parent
8967e35230
commit
2226292ce0
19 changed files with 348 additions and 384 deletions
|
@ -1,4 +1,4 @@
|
|||
use bevy::{prelude::*, asset, render::{Albedo, render_graph_2::{StandardMaterial, ShaderMaterials, ShaderMaterial, ShaderValue}}};
|
||||
use bevy::{prelude::*, asset, render::{Albedo, render_graph_2::{StandardMaterial, ShaderUniforms}}};
|
||||
|
||||
fn main() {
|
||||
AppBuilder::new().add_defaults_legacy().setup_world(setup).run();
|
||||
|
@ -11,53 +11,54 @@ fn setup(world: &mut World) {
|
|||
(texture_storage.add(texture))
|
||||
};
|
||||
|
||||
let mut color_shader_materials = ShaderMaterials::new();
|
||||
let mut color_shader_uniforms = ShaderUniforms::new();
|
||||
let color_material = StandardMaterial {
|
||||
albedo: Albedo::Color(math::vec4(1.0, 0.0, 0.0, 0.0))
|
||||
// albedo: Albedo::Color(math::vec4(1.0, 0.0, 0.0, 0.0))
|
||||
albedo: math::vec4(1.0, 0.0, 0.0, 0.0)
|
||||
};
|
||||
|
||||
color_shader_materials.add(color_material.get_selector());
|
||||
// color_shader_materials.add(color_material.get_selector());
|
||||
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
color_shader_materials,
|
||||
color_material,
|
||||
)],
|
||||
);
|
||||
// world.insert(
|
||||
// (),
|
||||
// vec![(
|
||||
// color_shader_materials,
|
||||
// color_material,
|
||||
// )],
|
||||
// );
|
||||
|
||||
let mut texture_shader_materials = ShaderMaterials::new();
|
||||
let texture_material = StandardMaterial {
|
||||
albedo: Albedo::Texture(texture_handle)
|
||||
};
|
||||
// let mut texture_shader_materials = ShaderMaterials::new();
|
||||
// let texture_material = StandardMaterial {
|
||||
// albedo: Albedo::Texture(texture_handle)
|
||||
// };
|
||||
|
||||
texture_shader_materials.add(texture_material.get_selector());
|
||||
// texture_shader_materials.add(texture_material.get_selector());
|
||||
|
||||
world.insert(
|
||||
(),
|
||||
vec![(
|
||||
texture_shader_materials,
|
||||
texture_material,
|
||||
)],
|
||||
);
|
||||
// world.insert(
|
||||
// (),
|
||||
// vec![(
|
||||
// texture_shader_materials,
|
||||
// texture_material,
|
||||
// )],
|
||||
// );
|
||||
|
||||
for (entity, materials) in <Read<ShaderMaterials>>::query().iter_entities(world) {
|
||||
println!("entity {}", entity);
|
||||
for selector in materials.materials.iter() {
|
||||
let shader_material = selector(entity, world).unwrap();
|
||||
print!(" ");
|
||||
for property in shader_material.iter_properties() {
|
||||
println!("property: {}", property);
|
||||
print!(" ");
|
||||
match shader_material.get_property(property) {
|
||||
Some(a) => match a {
|
||||
ShaderValue::Vec4(color) => println!("color {}", color),
|
||||
ShaderValue::Texture(ref handle) => println!("tex {}", handle.id),
|
||||
_ => println!("other"),
|
||||
},
|
||||
None => println!("none"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (entity, materials) in <Read<ShaderMaterials>>::query().iter_entities(world) {
|
||||
// println!("entity {}", entity);
|
||||
// for selector in materials.materials.iter() {
|
||||
// let shader_material = selector(entity, world).unwrap();
|
||||
// print!(" ");
|
||||
// for property in shader_material.iter_properties() {
|
||||
// println!("property: {}", property);
|
||||
// print!(" ");
|
||||
// match shader_material.get_property(property) {
|
||||
// Some(a) => match a {
|
||||
// ShaderValue::Vec4(color) => println!("color {}", color),
|
||||
// ShaderValue::Texture(ref handle) => println!("tex {}", handle.id),
|
||||
// _ => println!("other"),
|
||||
// },
|
||||
// None => println!("none"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 v_Normal;
|
||||
layout(location = 1) in vec4 v_Position;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform Material {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
void main() {
|
||||
// multiply the light by material color
|
||||
o_Target = Color;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
layout(location = 1) in vec4 a_Normal;
|
||||
layout(location = 2) in vec4 a_Uv;
|
||||
|
||||
layout(location = 0) out vec3 v_Normal;
|
||||
layout(location = 1) out vec4 v_Position;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform Object {
|
||||
mat4 Model;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform Material {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Normal = mat3(Model) * vec3(a_Normal.xyz);
|
||||
v_Position = Model * vec4(a_Pos);
|
||||
gl_Position = ViewProj * v_Position;
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
use crate::{asset::*, render::*};
|
||||
use legion::prelude::*;
|
||||
use wgpu::SwapChainOutput;
|
||||
|
||||
pub struct ForwardFlatPipeline {
|
||||
pub pipeline: Option<wgpu::RenderPipeline>,
|
||||
pub depth_format: wgpu::TextureFormat,
|
||||
pub bind_group: Option<wgpu::BindGroup>,
|
||||
pub msaa_samples: usize,
|
||||
}
|
||||
|
||||
impl ForwardFlatPipeline {
|
||||
pub fn new(msaa_samples: usize) -> Self {
|
||||
ForwardFlatPipeline {
|
||||
pipeline: None,
|
||||
bind_group: None,
|
||||
msaa_samples,
|
||||
depth_format: wgpu::TextureFormat::Depth32Float,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline for ForwardFlatPipeline {
|
||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
|
||||
let vs_bytes = shader::glsl_to_spirv(include_str!("forward_flat.vert"), shader::ShaderStage::Vertex);
|
||||
let fs_bytes =
|
||||
shader::glsl_to_spirv(include_str!("forward_flat.frag"), shader::ShaderStage::Fragment);
|
||||
|
||||
let bind_group_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1, // lights
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
self.bind_group = Some({
|
||||
let forward_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
let light_uniform_buffer = render_graph
|
||||
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
|
||||
.unwrap();
|
||||
|
||||
// Create bind group
|
||||
render_graph
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: forward_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 1,
|
||||
resource: light_uniform_buffer.get_binding_resource(),
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
let material_bind_group_layout = render_graph
|
||||
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
|
||||
.unwrap();
|
||||
|
||||
let pipeline_layout =
|
||||
render_graph
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
|
||||
});
|
||||
|
||||
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
|
||||
|
||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||
|
||||
self.pipeline = Some(render_graph.device.create_render_pipeline(
|
||||
&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
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::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[wgpu::ColorStateDescriptor {
|
||||
format: render_graph.swap_chain_descriptor.format,
|
||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: self.depth_format,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
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],
|
||||
sample_count: self.msaa_samples as u32,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
fn render(
|
||||
&mut self,
|
||||
render_graph: &RenderGraphData,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
_: &SwapChainOutput,
|
||||
world: &mut World,
|
||||
) {
|
||||
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
|
||||
|
||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut last_mesh_id = None;
|
||||
let mesh_query =
|
||||
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
||||
for (material, mesh) in mesh_query.iter(world) {
|
||||
let current_mesh_id = mesh.id;
|
||||
|
||||
let mut should_load_mesh = last_mesh_id == None;
|
||||
if let Some(last) = last_mesh_id {
|
||||
should_load_mesh = last != current_mesh_id;
|
||||
}
|
||||
|
||||
if should_load_mesh {
|
||||
if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
|
||||
mesh_asset.setup_buffers(&render_graph.device);
|
||||
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(ref mesh_asset) = mesh_storage.get(mesh.id) {
|
||||
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
|
||||
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
|
||||
};
|
||||
|
||||
last_mesh_id = Some(current_mesh_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, _: &RenderGraphData) {}
|
||||
|
||||
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.as_ref().unwrap()
|
||||
}
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
mod forward;
|
||||
mod forward_flat;
|
||||
mod forward_instanced;
|
||||
mod forward_shadow;
|
||||
mod shadow;
|
||||
mod ui;
|
||||
|
||||
pub use forward::{ForwardPass, ForwardPipeline, ForwardUniforms};
|
||||
pub use forward_flat::*;
|
||||
pub use forward_instanced::ForwardInstancedPipeline;
|
||||
pub use forward_shadow::ForwardShadowPassNew;
|
||||
pub use shadow::ShadowPass;
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph_2::{ShaderMaterials, RenderPass},
|
||||
render_graph_2::{ShaderUniforms, RenderPass},
|
||||
Instanced,
|
||||
},
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ pub fn mesh_draw_target(world: &World, _render_pass: &mut dyn RenderPass) {
|
|||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut last_mesh_id = None;
|
||||
let mesh_query =
|
||||
<(Read<ShaderMaterials>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
||||
<(Read<ShaderUniforms>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
||||
for (_material, mesh) in mesh_query.iter(world) {
|
||||
let current_mesh_id = mesh.id;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
pub mod pipelines;
|
||||
pub mod resource;
|
||||
pub mod resource_name;
|
||||
pub mod wgpu_renderer;
|
||||
mod resource_provider;
|
||||
mod resource;
|
||||
mod pipeline;
|
||||
mod pipeline_layout;
|
||||
mod pass;
|
||||
|
@ -16,3 +18,5 @@ pub use renderer::*;
|
|||
pub use shader::*;
|
||||
pub use render_graph::*;
|
||||
pub use draw_target::*;
|
||||
pub use resource::*;
|
||||
pub use resource_provider::*;
|
|
@ -22,7 +22,7 @@ pub struct Binding {
|
|||
|
||||
pub enum BindType {
|
||||
Uniform {
|
||||
// dynamic: bool,
|
||||
dynamic: bool,
|
||||
properties: Vec<UniformProperty>
|
||||
},
|
||||
Buffer {
|
||||
|
@ -45,6 +45,7 @@ pub struct UniformProperty {
|
|||
}
|
||||
|
||||
pub enum UniformPropertyType {
|
||||
// TODO: Add all types here
|
||||
Int,
|
||||
Float,
|
||||
UVec4,
|
||||
|
@ -55,6 +56,7 @@ pub enum UniformPropertyType {
|
|||
Array(Box<UniformPropertyType>, usize),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum TextureDimension {
|
||||
D1,
|
||||
D2,
|
||||
|
|
|
@ -9,11 +9,11 @@ layout(set = 0, binding = 0) uniform Camera {
|
|||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform Material {
|
||||
layout(set = 1, binding = 1) uniform StandardMaterial {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
void main() {
|
||||
// multiply the light by material color
|
||||
o_Target = Color;
|
||||
o_Target = Albedo;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ layout(set = 1, binding = 0) uniform Object {
|
|||
mat4 Model;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform Material {
|
||||
layout(set = 1, binding = 1) uniform StandardMaterial {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::render::{
|
|||
Vertex,
|
||||
{
|
||||
render_graph_2::{
|
||||
mesh_draw_target, resource, pipeline_layout::*, PassDescriptor, PipelineDescriptor,
|
||||
mesh_draw_target, resource_name, pipeline_layout::*, PassDescriptor, PipelineDescriptor,
|
||||
RenderGraphBuilder, RenderPassColorAttachmentDescriptor,
|
||||
},
|
||||
shader::{Shader, ShaderStage},
|
||||
|
@ -27,54 +27,40 @@ impl ForwardPipelineBuilder for RenderGraphBuilder {
|
|||
.add_bind_group(BindGroup {
|
||||
bindings: vec![
|
||||
Binding {
|
||||
name: "Globals".to_string(),
|
||||
name: "Camera".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![
|
||||
UniformProperty {
|
||||
name: "ViewProj".to_string(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
},
|
||||
UniformProperty {
|
||||
name: "NumLights".to_string(),
|
||||
property_type: UniformPropertyType::UVec4,
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
Binding {
|
||||
name: "Lights".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
properties: vec![
|
||||
UniformProperty {
|
||||
name: "SceneLights".to_string(),
|
||||
property_type: UniformPropertyType::Array(
|
||||
Box::new(UniformPropertyType::Struct(
|
||||
vec![
|
||||
UniformPropertyType::Mat4,
|
||||
UniformPropertyType::Vec4,
|
||||
UniformPropertyType::Vec4,
|
||||
]
|
||||
)),
|
||||
10
|
||||
),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
.add_bind_group(BindGroup {
|
||||
bindings: vec![
|
||||
Binding {
|
||||
name: "Entity".to_string(),
|
||||
name: "Object".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![
|
||||
UniformProperty {
|
||||
name: "World".to_string(),
|
||||
name: "Model".to_string(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
Binding {
|
||||
name: "StandardMaterial".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![
|
||||
UniformProperty {
|
||||
name: "Color".to_string(),
|
||||
name: "Albedo".to_string(),
|
||||
property_type: UniformPropertyType::Vec4,
|
||||
},
|
||||
]
|
||||
|
@ -121,7 +107,7 @@ impl ForwardPassBuilder for RenderGraphBuilder {
|
|||
"main",
|
||||
PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: resource::texture::SWAP_CHAIN.to_string(),
|
||||
attachment: resource_name::texture::SWAP_CHAIN.to_string(),
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::{asset::Mesh, legion::prelude::*, render::render_graph_2::RenderGraph};
|
||||
use crate::{asset::Mesh, legion::prelude::*, render::render_graph_2::{RenderGraph, Buffer, ResourceId}};
|
||||
|
||||
pub trait Renderer {
|
||||
fn initialize(&mut self, world: &mut World);
|
||||
fn resize(&mut self, world: &mut World, width: u32, height: u32);
|
||||
fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World);
|
||||
fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh);
|
||||
// TODO: swap out wgpu::BufferUsage for custom type
|
||||
fn create_buffer_with_data(&mut self, data: &[u8], buffer_usage: wgpu::BufferUsage) -> Buffer;
|
||||
fn free_buffer(&mut self, id: ResourceId) -> Buffer;
|
||||
}
|
||||
|
||||
pub trait RenderPass {
|
||||
|
|
8
src/render/render_graph_2/resource.rs
Normal file
8
src/render/render_graph_2/resource.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
pub type ResourceId = u64;
|
||||
|
||||
pub struct Buffer {
|
||||
pub id: ResourceId,
|
||||
pub size: u64,
|
||||
pub buffer_usage: wgpu::BufferUsage,
|
||||
// pub layout: Option<
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
pub mod texture;
|
|
@ -1 +0,0 @@
|
|||
pub const SWAP_CHAIN: &str = "swap_chain";
|
3
src/render/render_graph_2/resource_name.rs
Normal file
3
src/render/render_graph_2/resource_name.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod texture {
|
||||
pub const SWAP_CHAIN: &str = "SwapChain";
|
||||
}
|
41
src/render/render_graph_2/resource_provider.rs
Normal file
41
src/render/render_graph_2/resource_provider.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use crate::render::{render_graph_2::Renderer, ActiveCamera, Camera};
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
use std::mem;
|
||||
|
||||
trait ResourceProvider {
|
||||
fn update(renderer: &mut dyn Renderer, world: &mut World);
|
||||
fn resize(renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32);
|
||||
}
|
||||
|
||||
pub struct CameraResourceProvider;
|
||||
|
||||
impl ResourceProvider for CameraResourceProvider {
|
||||
fn update(renderer: &mut dyn Renderer, world: &mut World) {}
|
||||
fn resize(renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
||||
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();
|
||||
let matrix_size = mem::size_of::<[[f32; 4]; 4]>() as u64;
|
||||
// TODO: use staging buffer?
|
||||
let buffer = renderer.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::UNIFORM);
|
||||
// let temp_camera_buffer = render_graph
|
||||
// .device
|
||||
// .create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
// let forward_uniform_buffer = render_graph
|
||||
// .get_uniform_buffer(FORWARD_UNIFORM_BUFFER_NAME)
|
||||
// .unwrap();
|
||||
// encoder.copy_buffer_to_buffer(
|
||||
// &temp_camera_buffer,
|
||||
// 0,
|
||||
// &forward_uniform_buffer.buffer,
|
||||
// 0,
|
||||
// matrix_size,
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +1,134 @@
|
|||
use crate::prelude::*;
|
||||
use crate::{asset::Texture, legion::{prelude::{Entity, World}, borrow::{Ref, RefMap}}, render::Albedo};
|
||||
use crate::{
|
||||
asset::Texture,
|
||||
legion::{
|
||||
borrow::{Ref, RefMap},
|
||||
prelude::{Entity, World},
|
||||
},
|
||||
render::render_graph_2::{UniformPropertyType, Binding, BindType},
|
||||
render::Albedo,
|
||||
math::Vec4,
|
||||
};
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
|
||||
pub enum ShaderValue<'a> {
|
||||
Int(u32),
|
||||
Float(f32),
|
||||
Vec4(Vec4),
|
||||
Uniform(&'a [u8]),
|
||||
Texture(&'a Handle<Texture>),
|
||||
}
|
||||
|
||||
pub type ShaderMaterialSelector = fn(Entity, &World) -> Option<RefMap<&dyn ShaderMaterial>>;
|
||||
pub struct ShaderMaterials {
|
||||
pub type ShaderUniformSelector = fn(Entity, &World) -> Option<RefMap<&dyn AsUniforms>>;
|
||||
pub struct ShaderUniforms {
|
||||
// used for distinguishing
|
||||
pub materials: Vec<ShaderMaterialSelector>
|
||||
pub uniform_selectors: Vec<ShaderUniformSelector>,
|
||||
}
|
||||
|
||||
impl<'a> ShaderMaterials {
|
||||
impl<'a> ShaderUniforms {
|
||||
pub fn new() -> Self {
|
||||
ShaderMaterials {
|
||||
materials: Vec::new(),
|
||||
ShaderUniforms {
|
||||
uniform_selectors: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, selector: ShaderMaterialSelector) {
|
||||
self.materials.push(selector);
|
||||
pub fn add(&mut self, selector: ShaderUniformSelector) {
|
||||
self.uniform_selectors.push(selector);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ShaderMaterial {
|
||||
fn iter_properties(&self) -> std::slice::Iter<&'static str> ;
|
||||
fn get_property(&self, name: &str) -> Option<ShaderValue>;
|
||||
fn get_selector(&self) -> ShaderMaterialSelector;
|
||||
}
|
||||
|
||||
pub struct StandardMaterial {
|
||||
pub albedo: Albedo
|
||||
pub albedo: Vec4,
|
||||
}
|
||||
|
||||
// create this from a derive macro
|
||||
const STANDARD_MATERIAL_PROPERTIES: &[&str] = &["albedo"];
|
||||
impl ShaderMaterial for StandardMaterial {
|
||||
fn iter_properties(&self) -> std::slice::Iter<&'static str> {
|
||||
STANDARD_MATERIAL_PROPERTIES.iter()
|
||||
}
|
||||
fn get_property(&self, name: &str) -> Option<ShaderValue> {
|
||||
match name {
|
||||
"albedo" => Some(match self.albedo {
|
||||
Albedo::Color(color) => ShaderValue::Vec4(color),
|
||||
Albedo::Texture(ref texture) => ShaderValue::Texture(texture)
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn get_selector(&self) -> ShaderMaterialSelector {
|
||||
|entity, world| {
|
||||
world.get_component::<Self>(entity).map(
|
||||
|c: Ref<StandardMaterial>| {
|
||||
c.map_into(|s| {
|
||||
s as &dyn ShaderMaterial
|
||||
})
|
||||
}
|
||||
)
|
||||
pub trait GetBytes {
|
||||
fn get_bytes(&self) -> Vec<u8>;
|
||||
fn get_bytes_ref(&self) -> Option<&[u8]>;
|
||||
}
|
||||
|
||||
impl GetBytes for dyn AsBytes {
|
||||
fn get_bytes(&self) -> Vec<u8> {
|
||||
self.as_bytes().into()
|
||||
}
|
||||
|
||||
fn get_bytes_ref(&self) -> Option<&[u8]> {
|
||||
Some(self.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetBytes for Vec4 {
|
||||
fn get_bytes(&self) -> Vec<u8> {
|
||||
let vec4_array: [f32; 4] = (*self).into();
|
||||
vec4_array.as_bytes().into()
|
||||
}
|
||||
|
||||
fn get_bytes_ref(&self) -> Option<&[u8]> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsUniforms {
|
||||
fn get_uniform_info(&self) -> &[UniformInfo];
|
||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
||||
fn get_uniform_value(&self, index: usize) -> Vec<u8>;
|
||||
// TODO: support zero-copy uniforms
|
||||
// fn get_uniform_value_ref(&self, index: usize) -> &[u8];
|
||||
}
|
||||
|
||||
// pub struct UniformInfo<'a> {
|
||||
// pub name: &'a str,
|
||||
// pub
|
||||
// }
|
||||
|
||||
|
||||
// create this from a derive macro
|
||||
const STANDARD_MATERIAL_UNIFORM_INFO: &[UniformInfo] = &[
|
||||
UniformInfo {
|
||||
name: "StandardMaterial",
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: Vec::new()
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
// these are separate from BindType::Uniform{properties} because they need to be const
|
||||
const STANDARD_MATERIAL_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]];
|
||||
|
||||
pub struct UniformInfo<'a> {
|
||||
pub name: &'a str,
|
||||
pub bind_type: BindType,
|
||||
}
|
||||
|
||||
// const ST
|
||||
impl AsUniforms for StandardMaterial {
|
||||
fn get_uniform_info(&self) -> &[UniformInfo] {
|
||||
STANDARD_MATERIAL_UNIFORM_INFO
|
||||
}
|
||||
|
||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] {
|
||||
STANDARD_MATERIAL_UNIFORM_LAYOUTS
|
||||
}
|
||||
|
||||
fn get_uniform_value(&self, index: usize) -> Vec<u8> {
|
||||
match index {
|
||||
0 => self.albedo.get_bytes(),
|
||||
_ => panic!("index out of bounds"),
|
||||
}
|
||||
}
|
||||
// fn iter_properties(&self) -> std::slice::Iter<&'static str> {
|
||||
// STANDARD_MATERIAL_PROPERTIES.iter()
|
||||
// }
|
||||
// fn get_property(&self, name: &str) -> Option<ShaderValue> {
|
||||
// match name {
|
||||
// "albedo" => Some(match self.albedo {
|
||||
// Albedo::Color(color) => ShaderValue::Vec4(color),
|
||||
// Albedo::Texture(ref texture) => ShaderValue::Texture(texture)
|
||||
// }),
|
||||
// _ => None,
|
||||
// }
|
||||
// }
|
||||
// fn get_selector(&self) -> ShaderMaterialSelector {
|
||||
// |entity, world| {
|
||||
// world.get_component::<Self>(entity).map(
|
||||
// |c: Ref<StandardMaterial>| {
|
||||
// c.map_into(|s| {
|
||||
// s as &dyn ShaderMaterial
|
||||
// })
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use crate::{
|
||||
asset::Mesh,
|
||||
legion::prelude::*,
|
||||
render::render_graph_2::{
|
||||
resource, PassDescriptor, PipelineDescriptor, RenderGraph, RenderPass,
|
||||
RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, Renderer,
|
||||
resource_name, BindType, Buffer, PassDescriptor, PipelineDescriptor, RenderGraph,
|
||||
RenderPass, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, Renderer, TextureDimension,
|
||||
},
|
||||
};
|
||||
use std::{collections::HashMap, ops::Deref};
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub struct WgpuRenderer {
|
||||
pub device: wgpu::Device,
|
||||
|
@ -68,9 +67,34 @@ impl WgpuRenderer {
|
|||
None => None,
|
||||
};
|
||||
|
||||
let bind_group_layouts = pipeline_descriptor
|
||||
.pipeline_layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.map(|bind_group| {
|
||||
let bind_group_layout_binding = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, binding)| wgpu::BindGroupLayoutBinding {
|
||||
binding: i as u32,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: (&binding.bind_type).into()
|
||||
})
|
||||
.collect::<Vec<wgpu::BindGroupLayoutBinding>>();
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<wgpu::BindGroupLayout>>();
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[],
|
||||
bind_group_layouts: bind_group_layouts
|
||||
.iter()
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>()
|
||||
.as_slice(),
|
||||
});
|
||||
|
||||
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
|
@ -108,7 +132,6 @@ impl WgpuRenderer {
|
|||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
frame: &'a wgpu::SwapChainOutput,
|
||||
) -> wgpu::RenderPass<'a> {
|
||||
// TODO: fill this in
|
||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &pass_descriptor
|
||||
.color_attachments
|
||||
|
@ -128,7 +151,7 @@ impl WgpuRenderer {
|
|||
frame: &'a wgpu::SwapChainOutput,
|
||||
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
|
||||
let attachment = match color_attachment_descriptor.attachment.as_str() {
|
||||
resource::texture::SWAP_CHAIN => &frame.view,
|
||||
resource_name::texture::SWAP_CHAIN => &frame.view,
|
||||
_ => self
|
||||
.textures
|
||||
.get(&color_attachment_descriptor.attachment)
|
||||
|
@ -137,7 +160,7 @@ impl WgpuRenderer {
|
|||
|
||||
let resolve_target = match color_attachment_descriptor.resolve_target {
|
||||
Some(ref target) => match target.as_str() {
|
||||
resource::texture::SWAP_CHAIN => Some(&frame.view),
|
||||
resource_name::texture::SWAP_CHAIN => Some(&frame.view),
|
||||
_ => Some(&frame.view),
|
||||
},
|
||||
None => None,
|
||||
|
@ -158,7 +181,7 @@ impl WgpuRenderer {
|
|||
frame: &'a wgpu::SwapChainOutput,
|
||||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<&'a wgpu::TextureView> {
|
||||
let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() {
|
||||
resource::texture::SWAP_CHAIN => &frame.view,
|
||||
resource_name::texture::SWAP_CHAIN => &frame.view,
|
||||
_ => self
|
||||
.textures
|
||||
.get(&depth_stencil_attachment_descriptor.attachment)
|
||||
|
@ -197,7 +220,7 @@ impl Renderer for WgpuRenderer {
|
|||
.device
|
||||
.create_swap_chain(self.surface.as_ref().unwrap(), &self.swap_chain_descriptor);
|
||||
|
||||
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues
|
||||
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World.
|
||||
world.resources.insert(swap_chain);
|
||||
}
|
||||
|
||||
|
@ -242,24 +265,36 @@ impl Renderer for WgpuRenderer {
|
|||
let command_buffer = encoder.finish();
|
||||
self.queue.submit(&[command_buffer]);
|
||||
}
|
||||
|
||||
fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh) {
|
||||
if let None = mesh.vertex_buffer {
|
||||
self.buffers.insert(
|
||||
format!("meshv{}", asset_id),
|
||||
self.device
|
||||
.create_buffer_with_data(mesh.vertices.as_bytes(), wgpu::BufferUsage::VERTEX),
|
||||
);
|
||||
fn create_buffer_with_data(&mut self, data: &[u8], buffer_usage: wgpu::BufferUsage) -> Buffer {
|
||||
let buffer = self.device.create_buffer_with_data(data, buffer_usage);
|
||||
// TODO: FILL THIS IN
|
||||
Buffer {
|
||||
buffer_usage,
|
||||
size: data.len() as u64,
|
||||
id: 0,
|
||||
}
|
||||
}
|
||||
fn free_buffer(&mut self, id: super::ResourceId) -> super::Buffer {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
if let None = mesh.index_buffer {
|
||||
self.buffers.insert(
|
||||
format!("meshi{}", asset_id),
|
||||
self.device
|
||||
.create_buffer_with_data(mesh.indices.as_bytes(), wgpu::BufferUsage::INDEX),
|
||||
);
|
||||
}
|
||||
}
|
||||
// fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh) {
|
||||
// if let None = mesh.vertex_buffer {
|
||||
// self.buffers.insert(
|
||||
// format!("meshv{}", asset_id),
|
||||
// self.device
|
||||
// .create_buffer_with_data(mesh.vertices.as_bytes(), wgpu::BufferUsage::VERTEX),
|
||||
// );
|
||||
// }
|
||||
|
||||
// if let None = mesh.index_buffer {
|
||||
// self.buffers.insert(
|
||||
// format!("meshi{}", asset_id),
|
||||
// self.device
|
||||
// .create_buffer_with_data(mesh.indices.as_bytes(), wgpu::BufferUsage::INDEX),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub struct WgpuRenderPass<'a, 'b, 'c> {
|
||||
|
@ -272,3 +307,41 @@ impl<'a, 'b, 'c> RenderPass for WgpuRenderPass<'a, 'b, 'c> {
|
|||
self.render_pass.set_index_buffer(buffer, offset);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TextureDimension> for wgpu::TextureViewDimension {
|
||||
fn from(dimension: TextureDimension) -> Self {
|
||||
match dimension {
|
||||
TextureDimension::D1 => wgpu::TextureViewDimension::D1,
|
||||
TextureDimension::D2 => wgpu::TextureViewDimension::D2,
|
||||
TextureDimension::D2Array => wgpu::TextureViewDimension::D2Array,
|
||||
TextureDimension::Cube => wgpu::TextureViewDimension::Cube,
|
||||
TextureDimension::CubeArray => wgpu::TextureViewDimension::CubeArray,
|
||||
TextureDimension::D3 => wgpu::TextureViewDimension::D3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BindType> for wgpu::BindingType {
|
||||
fn from(bind_type: &BindType) -> Self {
|
||||
match bind_type {
|
||||
BindType::Uniform { dynamic, properties: _ } => {
|
||||
wgpu::BindingType::UniformBuffer { dynamic: *dynamic }
|
||||
}
|
||||
BindType::Buffer { dynamic, readonly } => {
|
||||
wgpu::BindingType::StorageBuffer { dynamic: *dynamic, readonly: *readonly }
|
||||
}
|
||||
BindType::SampledTexture {
|
||||
dimension,
|
||||
multisampled,
|
||||
} => wgpu::BindingType::SampledTexture {
|
||||
dimension: (*dimension).into(),
|
||||
multisampled: *multisampled,
|
||||
},
|
||||
BindType::Sampler => wgpu::BindingType::Sampler,
|
||||
BindType::StorageTexture { dimension } => {
|
||||
wgpu::BindingType::StorageTexture { dimension: (*dimension).into() }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue