Implement Shadows #24
|
@ -15,7 +15,7 @@ use crate::render::{
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
BasePassSlots, LightBasePassSlots, LightCullComputePassSlots, MeshBufferStorage, RenderAssets,
|
BasePassSlots, LightBasePassSlots, LightCullComputePassSlots, MeshBufferStorage, RenderAssets,
|
||||||
RenderMeshes,
|
RenderMeshes, ShadowMapsPassSlots,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
||||||
|
@ -26,6 +26,12 @@ pub enum MeshesPassSlots {
|
||||||
Material,
|
Material,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stores the bind group and bind group layout for the shadow atlas texture
|
||||||
|
struct ShadowsAtlasBgPair {
|
||||||
|
layout: Arc<wgpu::BindGroupLayout>,
|
||||||
|
bg: Arc<wgpu::BindGroup>,
|
||||||
|
}
|
||||||
|
|
||||||
//#[derive(Default)]
|
//#[derive(Default)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct MeshPass {
|
pub struct MeshPass {
|
||||||
|
@ -33,11 +39,14 @@ pub struct MeshPass {
|
||||||
|
|
||||||
pipeline: Option<RenderPipeline>,
|
pipeline: Option<RenderPipeline>,
|
||||||
material_bgl: Arc<wgpu::BindGroupLayout>,
|
material_bgl: Arc<wgpu::BindGroupLayout>,
|
||||||
transform_buffers: Option<ResourceData>,
|
|
||||||
// TODO: find a better way to extract these resources from the main world to be used in the
|
// TODO: find a better way to extract these resources from the main world to be used in the
|
||||||
// render stage.
|
// render stage.
|
||||||
|
transform_buffers: Option<ResourceData>,
|
||||||
render_meshes: Option<ResourceData>,
|
render_meshes: Option<ResourceData>,
|
||||||
mesh_buffers: Option<ResourceData>,
|
mesh_buffers: Option<ResourceData>,
|
||||||
|
|
||||||
|
shadows_atlas: Option<ShadowsAtlasBgPair>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeshPass {
|
impl MeshPass {
|
||||||
|
@ -46,43 +55,89 @@ impl MeshPass {
|
||||||
default_texture: None,
|
default_texture: None,
|
||||||
pipeline: None,
|
pipeline: None,
|
||||||
material_bgl,
|
material_bgl,
|
||||||
|
|
||||||
transform_buffers: None,
|
transform_buffers: None,
|
||||||
render_meshes: None,
|
render_meshes: None,
|
||||||
mesh_buffers: None,
|
mesh_buffers: None,
|
||||||
|
|
||||||
|
shadows_atlas: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_buffers(&self) -> AtomicRef<TransformBuffers> {
|
fn transform_buffers(&self) -> AtomicRef<TransformBuffers> {
|
||||||
self.transform_buffers
|
self.transform_buffers.as_ref().unwrap().get()
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_meshes(&self) -> AtomicRef<RenderMeshes> {
|
fn render_meshes(&self) -> AtomicRef<RenderMeshes> {
|
||||||
self.render_meshes
|
self.render_meshes.as_ref().unwrap().get()
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mesh_buffers(&self) -> AtomicRef<RenderAssets<MeshBufferStorage>> {
|
fn mesh_buffers(&self) -> AtomicRef<RenderAssets<MeshBufferStorage>> {
|
||||||
self.mesh_buffers
|
self.mesh_buffers.as_ref().unwrap().get()
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for MeshPass {
|
impl Node for MeshPass {
|
||||||
fn desc(
|
fn desc(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &mut crate::render::graph::RenderGraph,
|
graph: &mut crate::render::graph::RenderGraph,
|
||||||
) -> crate::render::graph::NodeDesc {
|
) -> crate::render::graph::NodeDesc {
|
||||||
// load the default texture
|
// load the default texture
|
||||||
//let bytes = include_bytes!("../../default_texture.png");
|
//let bytes = include_bytes!("../../default_texture.png");
|
||||||
//self.default_texture = Some(RenderTexture::from_bytes(device, &graph.queue, texture_bind_group_layout.clone(), bytes, "default_texture").unwrap());
|
//self.default_texture = Some(RenderTexture::from_bytes(device, &graph.queue, texture_bind_group_layout.clone(), bytes, "default_texture").unwrap());
|
||||||
|
|
||||||
|
let atlas_view = graph
|
||||||
|
.slot_value(ShadowMapsPassSlots::ShadowAtlasTextureView)
|
||||||
|
.expect("missing ShadowMapsPassSlots::ShadowAtlasTextureView")
|
||||||
|
.as_texture_view().unwrap();
|
||||||
|
let atlas_sampler = graph
|
||||||
|
.slot_value(ShadowMapsPassSlots::ShadowAtlasSampler)
|
||||||
|
.expect("missing ShadowMapsPassSlots::ShadowAtlasSampler")
|
||||||
|
.as_sampler().unwrap();
|
||||||
|
|
||||||
|
let device = graph.device();
|
||||||
|
let atlas_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
label: Some("bgl_shadows_atlas"),
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
sample_type: wgpu::TextureSampleType::Depth,
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
multisampled: false,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 1,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
let atlas_bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: Some("bg_shadows_atlas"),
|
||||||
|
layout: &atlas_layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::TextureView(atlas_view),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::Sampler(atlas_sampler),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
self.shadows_atlas = Some(ShadowsAtlasBgPair {
|
||||||
|
layout: Arc::new(atlas_layout),
|
||||||
|
bg: Arc::new(atlas_bg),
|
||||||
|
});
|
||||||
|
|
||||||
NodeDesc::new(
|
NodeDesc::new(
|
||||||
NodeType::Render,
|
NodeType::Render,
|
||||||
None,
|
None,
|
||||||
|
@ -107,13 +162,13 @@ impl Node for MeshPass {
|
||||||
let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights);
|
let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights);
|
||||||
let light_grid_bgl =
|
let light_grid_bgl =
|
||||||
graph.bind_group_layout(LightCullComputePassSlots::LightIndicesGridGroup);
|
graph.bind_group_layout(LightCullComputePassSlots::LightIndicesGridGroup);
|
||||||
|
let atlas_bgl = self.shadows_atlas.as_ref().unwrap().layout.clone();
|
||||||
|
|
||||||
let shader = Rc::new(Shader {
|
let shader = Rc::new(Shader {
|
||||||
label: Some("base_shader".into()),
|
label: Some("base_shader".into()),
|
||||||
source: include_str!("../../shaders/base.wgsl").to_string(),
|
source: include_str!("../../shaders/base.wgsl").to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let transforms = world
|
let transforms = world
|
||||||
.try_get_resource_data::<TransformBuffers>()
|
.try_get_resource_data::<TransformBuffers>()
|
||||||
.expect("Missing transform buffers");
|
.expect("Missing transform buffers");
|
||||||
|
@ -129,7 +184,6 @@ impl Node for MeshPass {
|
||||||
.expect("Missing render meshes");
|
.expect("Missing render meshes");
|
||||||
self.mesh_buffers = Some(mesh_buffers.clone());
|
self.mesh_buffers = Some(mesh_buffers.clone());
|
||||||
|
|
||||||
|
|
||||||
let transforms = transforms.get::<TransformBuffers>();
|
let transforms = transforms.get::<TransformBuffers>();
|
||||||
|
|
||||||
self.pipeline = Some(RenderPipeline::create(
|
self.pipeline = Some(RenderPipeline::create(
|
||||||
|
@ -142,6 +196,7 @@ impl Node for MeshPass {
|
||||||
camera_bgl.clone(),
|
camera_bgl.clone(),
|
||||||
lights_bgl.clone(),
|
lights_bgl.clone(),
|
||||||
light_grid_bgl.clone(),
|
light_grid_bgl.clone(),
|
||||||
|
atlas_bgl,
|
||||||
],
|
],
|
||||||
push_constant_ranges: vec![],
|
push_constant_ranges: vec![],
|
||||||
vertex: VertexState {
|
vertex: VertexState {
|
||||||
|
@ -202,6 +257,8 @@ impl Node for MeshPass {
|
||||||
|
|
||||||
let light_grid_bg = graph.bind_group(LightCullComputePassSlots::LightIndicesGridGroup);
|
let light_grid_bg = graph.bind_group(LightCullComputePassSlots::LightIndicesGridGroup);
|
||||||
|
|
||||||
|
let shadows_atlas_bg = &self.shadows_atlas.as_ref().unwrap().bg;
|
||||||
|
|
||||||
//let material_bg = graph.bind_group(MeshesPassSlots::Material);
|
//let material_bg = graph.bind_group(MeshesPassSlots::Material);
|
||||||
|
|
||||||
/* let pipeline = graph.pipeline(context.label.clone())
|
/* let pipeline = graph.pipeline(context.label.clone())
|
||||||
|
@ -284,6 +341,8 @@ impl Node for MeshPass {
|
||||||
|
|
||||||
pass.set_bind_group(4, light_grid_bg, &[]);
|
pass.set_bind_group(4, light_grid_bg, &[]);
|
||||||
|
|
||||||
|
pass.set_bind_group(5, shadows_atlas_bg, &[]);
|
||||||
|
|
||||||
// if this mesh uses indices, use them to draw the mesh
|
// if this mesh uses indices, use them to draw the mesh
|
||||||
if let Some((idx_type, indices)) = buffers.buffer_indices.as_ref() {
|
if let Some((idx_type, indices)) = buffers.buffer_indices.as_ref() {
|
||||||
let indices_len = indices.count() as u32;
|
let indices_len = indices.count() as u32;
|
||||||
|
|
|
@ -147,12 +147,13 @@ impl BasicRenderer {
|
||||||
forward_plus_graph.add_node(LightCullComputePassLabel, LightCullComputePass::new(size));
|
forward_plus_graph.add_node(LightCullComputePassLabel, LightCullComputePass::new(size));
|
||||||
|
|
||||||
debug!("Adding mesh pass");
|
debug!("Adding mesh pass");
|
||||||
|
forward_plus_graph.add_node(ShadowMapsPassLabel, ShadowMapsPass::new(&device));
|
||||||
|
|
||||||
let mesh_prep = MeshPrepNode::new(&device);
|
let mesh_prep = MeshPrepNode::new(&device);
|
||||||
let material_bgl = mesh_prep.material_bgl.clone();
|
let material_bgl = mesh_prep.material_bgl.clone();
|
||||||
forward_plus_graph.add_node(MeshPrepNodeLabel, mesh_prep);
|
forward_plus_graph.add_node(MeshPrepNodeLabel, mesh_prep);
|
||||||
forward_plus_graph.add_node(MeshesPassLabel, MeshPass::new(material_bgl));
|
forward_plus_graph.add_node(MeshesPassLabel, MeshPass::new(material_bgl));
|
||||||
|
|
||||||
forward_plus_graph.add_node(ShadowMapsPassLabel, ShadowMapsPass::new(&device));
|
|
||||||
|
|
||||||
forward_plus_graph.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
forward_plus_graph.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
||||||
forward_plus_graph.add_edge(MeshPrepNodeLabel, MeshesPassLabel);
|
forward_plus_graph.add_edge(MeshPrepNodeLabel, MeshesPassLabel);
|
||||||
|
|
|
@ -114,6 +114,11 @@ var<storage, read_write> u_light_indices: array<u32>;
|
||||||
@group(4) @binding(1)
|
@group(4) @binding(1)
|
||||||
var t_light_grid: texture_storage_2d<rg32uint, read_write>; // vec2<u32>
|
var t_light_grid: texture_storage_2d<rg32uint, read_write>; // vec2<u32>
|
||||||
|
|
||||||
|
@group(5) @binding(0)
|
||||||
|
var t_shadow_maps_atlas: texture_2d<f32>;
|
||||||
|
@group(5) @binding(1)
|
||||||
|
var s_shadow_maps_atlas: sampler;
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
if (u_camera.tile_debug == 1u) {
|
if (u_camera.tile_debug == 1u) {
|
||||||
|
|
Loading…
Reference in New Issue