diff --git a/res/shaders/depth.wgsl b/res/shaders/depth.wgsl index 836b945..d990c4a 100644 --- a/res/shaders/depth.wgsl +++ b/res/shaders/depth.wgsl @@ -13,5 +13,5 @@ fn vs_main( ); let world_position = model_matrix * vec4(model.position, 1.0); - return light.matrices[light.active_matrix] * world_position; + return light.matrices[light_matrix_index] * world_position; } diff --git a/res/shaders/globals.wgsl b/res/shaders/globals.wgsl index bef15c5..7f42142 100644 --- a/res/shaders/globals.wgsl +++ b/res/shaders/globals.wgsl @@ -12,11 +12,13 @@ struct Light { position: vec3, color: vec4, matrices: array, 6>, - active_matrix: u32, } @group(1) @binding(0) var light: Light; +@group(1) @binding(1) +var light_matrix_index: u32; + struct VertexInput { @location(0) position: vec3, @location(1) tex_coords: vec2, @@ -46,7 +48,7 @@ struct VertexOutput { // Fragment shader -@group(1)@binding(1) +@group(1)@binding(2) var t_light_depth: binding_array; -@group(1) @binding(2) +@group(1) @binding(3) var s_light_depth: binding_array; diff --git a/src/core/light.rs b/src/core/light.rs index cf59044..25cf305 100644 --- a/src/core/light.rs +++ b/src/core/light.rs @@ -11,7 +11,6 @@ pub struct LightUniform { _padding: u32, pub color: [f32; 4], pub matrices: [[[f32; 4]; 4]; 6], - pub active_matrix: u32, _padding2: [u32; 3], } @@ -20,12 +19,12 @@ impl LightUniform { let proj = cgmath::perspective(cgmath::Deg(90.0), 1.0, 0.1, 1000.0); #[rustfmt::skip] let matrices: [[[f32; 4]; 4]; 6] = [ - (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 1.0, 0.0, 0.0), Vector3::new(0.0,-1.0, 0.0))).into(), - (proj * Matrix4::look_to_rh(position.into(), Vector3::new(-1.0, 0.0, 0.0), Vector3::new(0.0,-1.0, 0.0))).into(), - (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0, 1.0, 0.0), Vector3::new(0.0, 0.0, 1.0))).into(), - (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0,-1.0, 0.0), Vector3::new(0.0, 0.0,-1.0))).into(), - (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0, 0.0, 1.0), Vector3::new(0.0,-1.0, 0.0))).into(), - (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0, 0.0,-1.0), Vector3::new(0.0,-1.0, 0.0))).into(), + (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 1.0, 0.0, 0.0), Vector3::new(0.0, 1.0, 0.0))).into(), + (proj * Matrix4::look_to_rh(position.into(), Vector3::new(-1.0, 0.0, 0.0), Vector3::new(0.0, 1.0, 0.0))).into(), + (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0, 1.0, 0.0), Vector3::new(1.0, 0.0, 0.0))).into(), + (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0,-1.0, 0.0), Vector3::new(-1.0, 0.0, 0.0))).into(), + (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0, 0.0, 1.0), Vector3::new(0.0, 1.0, 0.0))).into(), + (proj * Matrix4::look_to_rh(position.into(), Vector3::new( 0.0, 0.0,-1.0), Vector3::new(0.0, 1.0, 0.0))).into(), ]; Self { @@ -33,7 +32,6 @@ impl LightUniform { _padding: 0, color, matrices: matrices, - active_matrix: 0, _padding2: [0, 0, 0] } } diff --git a/src/core/state.rs b/src/core/state.rs index b28aa4a..d010bee 100644 --- a/src/core/state.rs +++ b/src/core/state.rs @@ -39,6 +39,8 @@ pub struct State { light_bind_group: wgpu::BindGroup, light_depth_pass: RenderPass, light_depth_textures: [Texture; 6], + light_matrix_uniform: u32, + light_matrix_buffer: wgpu::Buffer, } impl State { @@ -167,11 +169,18 @@ impl State { // We'll want to update our lights position, so we use COPY_DST let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Light VB"), + label: Some("Light UB"), contents: bytemuck::cast_slice(&[light_uniform]), usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, }); + let light_matrix_uniform = 0; + let light_matrix_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Light Matrix UB"), + contents: bytemuck::cast_slice(&[light_matrix_uniform]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + let light_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[ @@ -186,9 +195,20 @@ impl State { }, count: None, }, - // depth + // matrix index wgpu::BindGroupLayoutEntry { binding: 1, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + // depth textures + wgpu::BindGroupLayoutEntry { + binding: 2, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { multisampled: false, @@ -198,7 +218,7 @@ impl State { count: NonZeroU32::new(6), }, wgpu::BindGroupLayoutEntry { - binding: 2, + binding: 3, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Comparison), count: NonZeroU32::new(6), @@ -210,16 +230,23 @@ impl State { let light_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &light_bind_group_layout, entries: &[ + // light struct wgpu::BindGroupEntry { binding: 0, resource: light_buffer.as_entire_binding(), }, + // matrix index wgpu::BindGroupEntry { binding: 1, + resource: light_matrix_buffer.as_entire_binding(), + }, + // depth textures + wgpu::BindGroupEntry { + binding: 2, resource: wgpu::BindingResource::TextureViewArray(&light_depth_texture_views), }, wgpu::BindGroupEntry { - binding: 2, + binding: 3, resource: wgpu::BindingResource::SamplerArray(&light_depth_texture_samplers), }, ], @@ -380,6 +407,8 @@ impl State { light_bind_group, light_depth_pass, light_depth_textures, + light_matrix_uniform, + light_matrix_buffer, } } @@ -444,27 +473,25 @@ impl State { } pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> { - let surface_texture = self.surface.get_current_texture()?; - let surface_view = surface_texture - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }); - encoder.push_debug_group("shadow passes"); + // render light to depth textures for i in 0..6 { - self.light_uniform.active_matrix = i as u32; + self.light_matrix_uniform = i as u32; self.queue.write_buffer( - &self.light_buffer, + &self.light_matrix_buffer, 0, - bytemuck::cast_slice(&[self.light_uniform]), + bytemuck::cast_slice(&[self.light_matrix_uniform]), ); - let mut light_depth_render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + let mut depth_encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Depth Encoder"), + }); + + { + let mut light_depth_render_pass = + depth_encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Light Depth Render Pass"), color_attachments: &[], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { @@ -477,17 +504,30 @@ impl State { }), }); - light_depth_render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); - light_depth_render_pass.set_pipeline(&self.light_depth_pass.pipeline); - // TODO separate func - light_depth_render_pass.draw_model_instanced( - &self.model, - 0..self.instances.len() as u32, - &self.camera_bind_group, - &self.light_bind_group, - ); + light_depth_render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); + light_depth_render_pass.set_pipeline(&self.light_depth_pass.pipeline); + // TODO separate func + light_depth_render_pass.draw_model_instanced( + &self.model, + 0..self.instances.len() as u32, + &self.camera_bind_group, + &self.light_bind_group, + ); + } + + self.queue.submit(std::iter::once(depth_encoder.finish())); } - encoder.pop_debug_group(); + + // render geometry + let surface_texture = self.surface.get_current_texture()?; + let surface_view = surface_texture + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); encoder.push_debug_group("geometry pass"); {