use crate::postprocess::ScreenVertex; pub struct DebugOverlay { pipeline_shadow: wgpu::RenderPipeline, pipeline_snow_light: wgpu::RenderPipeline, shadow_bind_group_layout: wgpu::BindGroupLayout, snow_light_bind_group_layout: wgpu::BindGroupLayout, } impl DebugOverlay { pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self { let shader_source = std::fs::read_to_string("src/shaders/debug_overlay.wgsl") .expect("Failed to read debug_overlay.wgsl"); let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("Debug Overlay Shader"), source: wgpu::ShaderSource::Wgsl(shader_source.into()), }); let shadow_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("Shadow Debug Bind Group Layout"), entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Depth, view_dimension: wgpu::TextureViewDimension::D2Array, multisampled: false, }, count: None, }], }); let snow_light_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("Snow Light Debug Bind Group Layout"), entries: &[ wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, ], }); let shadow_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Shadow Debug Pipeline Layout"), bind_group_layouts: &[&shadow_bind_group_layout], immediate_size: 0, }); let snow_light_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Snow Light Debug Pipeline Layout"), bind_group_layouts: &[&snow_light_bind_group_layout], immediate_size: 0, }); let color_target = wgpu::ColorTargetState { format, blend: Some(wgpu::BlendState::REPLACE), write_mask: wgpu::ColorWrites::ALL, }; let pipeline_shadow = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Shadow Debug Pipeline"), layout: Some(&shadow_layout), vertex: wgpu::VertexState { module: &shader, entry_point: Some("vs_main"), buffers: &[ScreenVertex::desc()], compilation_options: Default::default(), }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: Some("fs_shadow_map"), targets: &[Some(color_target.clone())], compilation_options: Default::default(), }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, cull_mode: None, ..Default::default() }, depth_stencil: None, multisample: wgpu::MultisampleState::default(), multiview_mask: None, cache: None, }); let pipeline_snow_light = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Snow Light Debug Pipeline"), layout: Some(&snow_light_layout), vertex: wgpu::VertexState { module: &shader, entry_point: Some("vs_main"), buffers: &[ScreenVertex::desc()], compilation_options: Default::default(), }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: Some("fs_snow_light"), targets: &[Some(color_target)], compilation_options: Default::default(), }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, cull_mode: None, ..Default::default() }, depth_stencil: None, multisample: wgpu::MultisampleState::default(), multiview_mask: None, cache: None, }); Self { pipeline_shadow, pipeline_snow_light, shadow_bind_group_layout, snow_light_bind_group_layout, } } pub fn render_shadow_map( &self, encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView, shadow_view: &wgpu::TextureView, quad_vb: &wgpu::Buffer, quad_ib: &wgpu::Buffer, quad_num_indices: u32, device: &wgpu::Device, ) { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("Shadow Debug Bind Group"), layout: &self.shadow_bind_group_layout, entries: &[wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::TextureView(shadow_view), }], }); let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Shadow Debug Pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: target, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Load, store: wgpu::StoreOp::Store, }, depth_slice: None, })], depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, multiview_mask: None, }); pass.set_pipeline(&self.pipeline_shadow); pass.set_bind_group(0, &bind_group, &[]); pass.set_vertex_buffer(0, quad_vb.slice(..)); pass.set_index_buffer(quad_ib.slice(..), wgpu::IndexFormat::Uint16); pass.draw_indexed(0..quad_num_indices, 0, 0..1); } pub fn render_snow_light( &self, encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView, snow_light_view: &wgpu::TextureView, snow_light_sampler: &wgpu::Sampler, quad_vb: &wgpu::Buffer, quad_ib: &wgpu::Buffer, quad_num_indices: u32, device: &wgpu::Device, ) { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("Snow Light Debug Bind Group"), layout: &self.snow_light_bind_group_layout, entries: &[ wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::TextureView(snow_light_view), }, wgpu::BindGroupEntry { binding: 2, resource: wgpu::BindingResource::Sampler(snow_light_sampler), }, ], }); let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Snow Light Debug Pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: target, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Load, store: wgpu::StoreOp::Store, }, depth_slice: None, })], depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, multiview_mask: None, }); pass.set_pipeline(&self.pipeline_snow_light); pass.set_bind_group(0, &bind_group, &[]); pass.set_vertex_buffer(0, quad_vb.slice(..)); pass.set_index_buffer(quad_ib.slice(..), wgpu::IndexFormat::Uint16); pass.draw_indexed(0..quad_num_indices, 0, 0..1); } }