Got rid of the worst of the cull popping

This commit is contained in:
Joshua Barretto 2023-02-09 15:52:33 +00:00
parent 7fa654ae4c
commit 0d0b7a8889
2 changed files with 45 additions and 27 deletions

View File

@ -976,11 +976,11 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
col_lights: &'data Arc<ColLights<terrain::Locals>>,
locals: &'data terrain::BoundLocals,
alt_indices: &'data crate::scene::terrain::AltIndices,
is_underground: bool,
is_underground: Option<bool>,
) {
// 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<sprite::Instance>,
alt_indices: &'data crate::scene::terrain::AltIndices,
is_underground: bool,
is_underground: Option<bool>,
) {
// 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());

View File

@ -1645,17 +1645,26 @@ impl<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
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()