diff --git a/lyra-game/src/render/graph/passes/meshes.rs b/lyra-game/src/render/graph/passes/meshes.rs index 46f67ed..75e190d 100644 --- a/lyra-game/src/render/graph/passes/meshes.rs +++ b/lyra-game/src/render/graph/passes/meshes.rs @@ -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 = diff --git a/lyra-game/src/render/graph/passes/shadows.rs b/lyra-game/src/render/graph/passes/shadows.rs index dbbfe36..cb2cc55 100644 --- a/lyra-game/src/render/graph/passes/shadows.rs +++ b/lyra-game/src/render/graph/passes/shadows.rs @@ -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, 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()), diff --git a/lyra-game/src/render/renderer.rs b/lyra-game/src/render/renderer.rs index da9dd1d..e162f55 100755 --- a/lyra-game/src/render/renderer.rs +++ b/lyra-game/src/render/renderer.rs @@ -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 diff --git a/lyra-game/src/render/shaders/base.wgsl b/lyra-game/src/render/shaders/base.wgsl index 3eefbf0..b695844 100755 --- a/lyra-game/src/render/shaders/base.wgsl +++ b/lyra-game/src/render/shaders/base.wgsl @@ -118,6 +118,8 @@ var t_light_grid: texture_storage_2d; // vec2 var t_shadow_maps_atlas: texture_2d; @group(5) @binding(1) var s_shadow_maps_atlas: sampler; +@group(5) @binding(2) +var u_light_space_matrix: mat4x4; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 {