From 0d0b7a88896dd8c553ed996b2c81cf5410f58e03 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 9 Feb 2023 15:52:33 +0000 Subject: [PATCH] Got rid of the worst of the cull popping --- voxygen/src/render/renderer/drawer.rs | 30 ++++++++++--------- voxygen/src/scene/terrain.rs | 42 ++++++++++++++++++--------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index e7e2aba445..569f6bdcc0 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -976,11 +976,11 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { col_lights: &'data Arc>, locals: &'data terrain::BoundLocals, alt_indices: &'data crate::scene::terrain::AltIndices, - is_underground: bool, + is_underground: Option, ) { // Don't render anything if there's nothing to render! - if (alt_indices.underground_end == 0 && is_underground) - || (alt_indices.deep_end == model.len() && !is_underground) + if (alt_indices.underground_end == 0 && is_underground == Some(true)) + || (alt_indices.deep_end == model.len() && is_underground == Some(false)) { return; } @@ -998,10 +998,10 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> { self.render_pass.set_bind_group(3, &locals.bind_group, &[]); - let submodel = if is_underground { - model.submodel(0..alt_indices.underground_end as u32) - } else { - model.submodel(alt_indices.deep_end as u32..model.len() as u32) + let submodel = match is_underground { + Some(true) => model.submodel(0..alt_indices.underground_end as u32), + Some(false) => model.submodel(alt_indices.deep_end as u32..model.len() as u32), + None => model.submodel(0..model.len() as u32), }; self.render_pass.set_vertex_buffer(0, submodel.buf()); @@ -1044,11 +1044,11 @@ impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { terrain_locals: &'data terrain::BoundLocals, instances: &'data Instances, alt_indices: &'data crate::scene::terrain::AltIndices, - is_underground: bool, + is_underground: Option, ) { // Don't render anything if there's nothing to render! - if (alt_indices.underground_end == 0 && is_underground) - || (alt_indices.deep_end == instances.count() && !is_underground) + if (alt_indices.underground_end == 0 && is_underground == Some(true)) + || (alt_indices.deep_end == instances.count() && is_underground == Some(false)) { return; } @@ -1056,10 +1056,12 @@ impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> { self.render_pass .set_bind_group(3, &terrain_locals.bind_group, &[]); - let subinstances = if is_underground { - instances.subinstances(0..alt_indices.underground_end as u32) - } else { - instances.subinstances(alt_indices.deep_end as u32..instances.count() as u32) + let subinstances = match is_underground { + Some(true) => instances.subinstances(0..alt_indices.underground_end as u32), + Some(false) => { + instances.subinstances(alt_indices.deep_end as u32..instances.count() as u32) + }, + None => instances.subinstances(0..instances.count() as u32), }; self.render_pass.set_vertex_buffer(0, subinstances.buf()); diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 505439779e..41a6160e9d 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1645,17 +1645,26 @@ impl Terrain { Spiral2d::new() .filter_map(|rpos| { let pos = focus_chunk + rpos; - self.chunks.get(&pos) + Some((rpos, self.chunks.get(&pos)?)) }) .take(self.chunks.len()) - .filter(|chunk| chunk.visible.is_visible()) - .filter_map(|chunk| { - chunk - .opaque_model - .as_ref() - .map(|model| (model, &chunk.col_lights, &chunk.locals, &chunk.alt_indices)) + .filter(|(_, chunk)| chunk.visible.is_visible()) + .filter_map(|(rpos, chunk)| { + Some(( + rpos, + chunk.opaque_model.as_ref()?, + &chunk.col_lights, + &chunk.locals, + &chunk.alt_indices, + )) }) - .for_each(|(model, col_lights, locals, alt_indices)| { + .for_each(|(rpos, model, col_lights, locals, alt_indices)| { + // Always draw all of close chunks to avoid terrain 'popping' + let is_underground = if rpos.magnitude_squared() < 3i32.pow(2) { + None + } else { + Some(is_underground) + }; drawer.draw(model, col_lights, locals, alt_indices, is_underground) }); } @@ -1677,7 +1686,7 @@ impl Terrain { let chunk_iter = Spiral2d::new() .filter_map(|rpos| { let pos = focus_chunk + rpos; - self.chunks.get(&pos).map(|c| (pos, c)) + Some((rpos, pos, self.chunks.get(&pos)?)) }) .take(self.chunks.len()); @@ -1694,8 +1703,8 @@ impl Terrain { let mut sprite_drawer = drawer.draw_sprites(&self.sprite_globals, &self.sprite_col_lights); chunk_iter .clone() - .filter(|(_, c)| c.visible.is_visible()) - .for_each(|(pos, chunk)| { + .filter(|(_, _, c)| c.visible.is_visible()) + .for_each(|(rpos, pos, chunk)| { // Skip chunk if it has no sprites if chunk.sprite_instances[0].0.count() == 0 { return; @@ -1723,6 +1732,13 @@ impl Terrain { 4 }; + // Always draw all of close chunks to avoid terrain 'popping' + let is_underground = if rpos.magnitude_squared() < 3i32.pow(2) { + None + } else { + Some(is_underground) + }; + sprite_drawer.draw( &chunk.locals, &chunk.sprite_instances[lod_level].0, @@ -1738,8 +1754,8 @@ impl Terrain { span!(guard, "Fluid chunks"); let mut fluid_drawer = drawer.draw_fluid(); chunk_iter - .filter(|(_, chunk)| chunk.visible.is_visible()) - .filter_map(|(_, chunk)| { + .filter(|(_, _, chunk)| chunk.visible.is_visible()) + .filter_map(|(_, _, chunk)| { chunk .fluid_model .as_ref()