diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 4f8ee4cc95..5835e4475a 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -20,6 +20,7 @@ pub struct CharSelectionState { char_selection_ui: CharSelectionUi, client: Rc>, scene: Scene, + need_shadow_clear: bool, } impl CharSelectionState { @@ -36,6 +37,7 @@ impl CharSelectionState { char_selection_ui, client, scene, + need_shadow_clear: false, } } @@ -71,6 +73,9 @@ impl PlayState for CharSelectionState { // Set scale mode in case it was change self.char_selection_ui .set_scale_mode(global_state.settings.interface.ui_scale); + + // Clear shadow textures since we don't render to them here + self.need_shadow_clear = true; } fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { @@ -233,6 +238,11 @@ impl PlayState for CharSelectionState { None => return, }; + if self.need_shadow_clear { + drawer.clear_shadows(); + self.need_shadow_clear = false; + } + let client = self.client.borrow(); let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 9ae24a42fe..ead94a6474 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -170,6 +170,7 @@ impl<'a> Drawer<'a> { let data = bytemuck::cast_slice(matrices); for face in 0..6 { + // TODO: view creation cost? let view = shadow_renderer .point_depth @@ -185,7 +186,7 @@ impl<'a> Drawer<'a> { array_layer_count: NonZeroU32::new(1), }); - let label = format!("point shadow face: {} pass", face); + let label = format!("point shadow face-{} pass", face); let mut render_pass = self.encoder .as_mut() @@ -224,6 +225,72 @@ impl<'a> Drawer<'a> { } } } + + /// Clear all the shadow textures, useful if directed shadows (shadow_pass) + /// and point light shadows (draw_point_shadows) are unused and thus the + /// textures will otherwise not be cleared after either their + /// initialization or their last use + /// NOTE: could simply use the above passes except `draw_point_shadows` + /// requires an array of matrices that could be a pain to construct + /// simply for clearing + pub fn clear_shadows(&mut self) { + if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map { + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("clear directed shadow pass"), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &shadow_renderer.directed_depth.view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + + for face in 0..6 { + // TODO: view creation cost? + let view = + shadow_renderer + .point_depth + .tex + .create_view(&wgpu::TextureViewDescriptor { + label: Some("Point shadow cubemap face"), + format: None, + dimension: Some(wgpu::TextureViewDimension::D2), + aspect: wgpu::TextureAspect::DepthOnly, + base_mip_level: 0, + level_count: None, + base_array_layer: face, + array_layer_count: NonZeroU32::new(1), + }); + + let label = format!("clear point shadow face-{} pass", face); + self.encoder + .as_mut() + .unwrap() + .begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(&label), + color_attachments: &[], + depth_stencil_attachment: Some( + wgpu::RenderPassDepthStencilAttachmentDescriptor { + attachment: &view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }, + ), + }); + } + } + } } impl<'a> Drop for Drawer<'a> {