Implement Shadows #24

Merged
SeanOMik merged 28 commits from feat/shadow-maps into main 2024-08-10 03:10:30 +00:00
4 changed files with 94 additions and 54 deletions
Showing only changes of commit 6c6893149a - Show all commits

View File

@ -86,58 +86,6 @@ impl Node for MeshPass {
//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());
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(
NodeType::Render,
None,
@ -158,6 +106,82 @@ impl Node for MeshPass {
let device = graph.device();
let surface_config_format = graph.view_target().format();
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 dir_light_projection_buf = graph
.slot_value(ShadowMapsPassSlots::DirLightProjectionBuffer)
.expect("missing ShadowMapsPassSlots::DirLightProjectionBuffer")
.as_buffer()
.unwrap();
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,
},
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
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),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: dir_light_projection_buf,
offset: 0,
size: None,
}),
},
],
});
self.shadows_atlas = Some(ShadowsAtlasBgPair {
layout: Arc::new(atlas_layout),
bg: Arc::new(atlas_bg),
});
let camera_bgl = graph.bind_group_layout(BasePassSlots::Camera);
let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights);
let light_grid_bgl =

View File

@ -27,13 +27,14 @@ pub enum ShadowMapsPassSlots {
ShadowAtlasTexture,
ShadowAtlasTextureView,
ShadowAtlasSampler,
DirLightProjectionBuffer,
}
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
pub struct ShadowMapsPassLabel;
struct LightDepthMap {
light_projection_buffer: wgpu::Buffer,
light_projection_buffer: Arc<wgpu::Buffer>,
bindgroup: wgpu::BindGroup,
}
@ -158,7 +159,7 @@ impl ShadowMapsPass {
self.depth_maps.insert(
entity,
LightDepthMap {
light_projection_buffer,
light_projection_buffer: Arc::new(light_projection_buffer),
bindgroup: bg,
},
);
@ -202,6 +203,12 @@ impl Node for ShadowMapsPass {
Some(SlotValue::Sampler(self.atlas_sampler.clone())),
);
node.add_sampler_slot(
ShadowMapsPassSlots::DirLightProjectionBuffer,
SlotAttribute::Output,
Some(SlotValue::Lazy),
);
node
}
@ -222,6 +229,12 @@ impl Node for ShadowMapsPass {
}
}
// update the light projection buffer slot
let (_, dir_depth_map) = self.depth_maps.iter().next().unwrap();
let val = graph.slot_value_mut(ShadowMapsPassSlots::DirLightProjectionBuffer)
.unwrap();
*val = SlotValue::Buffer(dir_depth_map.light_projection_buffer.clone());
if self.pipeline.is_none() {
let shader = Rc::new(Shader {
label: Some("shader_shadows".into()),

View File

@ -156,6 +156,7 @@ impl BasicRenderer {
forward_plus_graph.add_edge(LightBasePassLabel, LightCullComputePassLabel);
forward_plus_graph.add_edge(LightCullComputePassLabel, MeshesPassLabel);
forward_plus_graph.add_edge(MeshPrepNodeLabel, MeshesPassLabel);
// run ShadowMapsPass after MeshPrep and before MeshesPass

View File

@ -118,6 +118,8 @@ var t_light_grid: texture_storage_2d<rg32uint, read_write>; // vec2<u32>
var t_shadow_maps_atlas: texture_2d<f32>;
@group(5) @binding(1)
var s_shadow_maps_atlas: sampler;
@group(5) @binding(2)
var<uniform> u_light_space_matrix: mat4x4<f32>;
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {