mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge pull request #11680 from kacpherek/fix/near-chunks-no-xray
🤖 Agent: near sections no longer dither over far terrain (fade() is 0 or lod::HELD), and the replaced tile still stays behind for lod::FADE through previous, so no hole opens; the test bound lowered to 1,000 matches the half that now come in whole.
This commit is contained in:
1 file changed
+25
-24
@@ -471,9 +471,9 @@ struct SectionGpu {
|
||||
/// while its instance carries a fade (`drawn_faded`), and GPU culling's
|
||||
/// pass leaves it out.
|
||||
gpu_fading: bool,
|
||||
/// When it began to fade in over the far terrain it replaces, which
|
||||
/// stays whole behind it until then: a section new where far tiles are
|
||||
/// drawn. Meshed again, it stays as it was.
|
||||
/// When it came in over the far terrain it replaces (drawn whole at once,
|
||||
/// `fade`): a section new where far tiles are drawn, which skips vanilla's
|
||||
/// fade-in. Meshed again, it stays as it was.
|
||||
fading: Option<std::time::Instant>,
|
||||
/// When it began to fade out, its column gone over far terrain that
|
||||
/// stays behind it (`Renderer::leave_section`); released once it has.
|
||||
@@ -495,17 +495,19 @@ pub(crate) fn collect_animated_layers(
|
||||
}
|
||||
|
||||
impl SectionGpu {
|
||||
/// Its fade code this frame (`lod::fade_code`), 0 once whole. `retiring`:
|
||||
/// its column has left the render distance, far terrain is coming in
|
||||
/// under it (`lod::HELD`).
|
||||
fn fade(&self, now: std::time::Instant, retiring: bool) -> u32 {
|
||||
match self.leaving {
|
||||
Some(since) => lod::fade_out_code(since, 0, now),
|
||||
None if retiring => lod::HELD,
|
||||
None => self
|
||||
.fading
|
||||
.and_then(|since| lod::fade_code(Some(since), 0, now))
|
||||
.unwrap_or(0),
|
||||
/// Its fade code this frame: 0, drawn whole, or `lod::HELD` (whole, in
|
||||
/// front of far terrain) while it leaves (`leaving`) or its column has left
|
||||
/// the render distance and far terrain is coming in under it (`retiring`).
|
||||
/// A near section never dithers over far terrain: the holes of its pattern
|
||||
/// showed its own inside (cave walls, the stone under the grass), nearer
|
||||
/// than the tile behind, an x-ray of each column coming in or going out.
|
||||
/// It comes in whole over the tile it replaces, which stays behind it until
|
||||
/// `fading` is `lod::FADE` old, and leaves whole after as long.
|
||||
fn fade(&self, retiring: bool) -> u32 {
|
||||
if self.leaving.is_some() || retiring {
|
||||
lod::HELD
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// Its vertices in `arena`, and in `translucent_arena` when `split` (there
|
||||
@@ -571,23 +573,21 @@ impl SectionGpu {
|
||||
/// once false, this stays false until the section is meshed again, leaves,
|
||||
/// is held (`lod_retiring`), or the chunk fade-in time changes.
|
||||
fn drawn_faded(&self, key: SectionKey, f: FadeInputs<'_>) -> bool {
|
||||
let fade = self.fade(f.now, f.retiring.contains(&key));
|
||||
let fade = self.fade(f.retiring.contains(&key));
|
||||
let visibility = section_visibility(f.uploaded.get(&key), f.fade_ms, f.now);
|
||||
section_instance([0.0; 3], fade, visibility)[3].to_bits()
|
||||
!= section_instance([0.0; 3], 0, 1.0)[3].to_bits()
|
||||
}
|
||||
/// When its fade is over at the latest (`drawn_faded`): the later of the
|
||||
/// ends of its fade-in over far terrain (`fading` and `lod::FADE`, a few
|
||||
/// milliseconds after `fade` reaches 0) and of vanilla's (its first upload
|
||||
/// and `f.fade_ms`). None while it leaves or is held, which ends only when
|
||||
/// it goes or is meshed again, and without either fade-in.
|
||||
/// When its fade is over at the latest (`drawn_faded`): the end of
|
||||
/// vanilla's fade-in (its first upload and `f.fade_ms`; one coming in over
|
||||
/// far terrain is whole at once, `fade`). None while it leaves or is held,
|
||||
/// which ends only when it goes or is meshed again, and without a fade-in.
|
||||
fn fade_end(&self, key: SectionKey, f: FadeInputs<'_>) -> Option<Instant> {
|
||||
if self.leaving.is_some() || f.retiring.contains(&key) {
|
||||
return None;
|
||||
}
|
||||
let vanilla = f.uploaded.get(&key).filter(|_| f.fade_ms > 0);
|
||||
let vanilla = vanilla.map(|&t| t + std::time::Duration::from_millis(f.fade_ms));
|
||||
vanilla.max(self.fading.map(|t| t + lod::FADE))
|
||||
vanilla.map(|&t| t + std::time::Duration::from_millis(f.fade_ms))
|
||||
}
|
||||
}
|
||||
/// Which of a mesh's ranges `move_off_page` moves: what it holds in the section
|
||||
@@ -8155,7 +8155,7 @@ impl Renderer {
|
||||
let fading_over_lods = self.sections_fading_over_lods(now);
|
||||
let fade_code = move |section: &SectionGpu, key: &SectionKey| {
|
||||
if fading_over_lods {
|
||||
section.fade(now, retiring.contains(key))
|
||||
section.fade(retiring.contains(key))
|
||||
} else {
|
||||
0
|
||||
}
|
||||
@@ -13473,7 +13473,8 @@ mod tests {
|
||||
last = now;
|
||||
}
|
||||
assert!(set_by.iter().all(|&n| n > 20), "flags set {set_by:?}");
|
||||
assert!(handed_back > 2_000, "{handed_back} handed back");
|
||||
// Over a thousand: the half of the uploads over far terrain come in whole.
|
||||
assert!(handed_back > 1_000, "{handed_back} handed back");
|
||||
// Switched off with sections still flagged: none keeps a record or a
|
||||
// flag, and each is marked as while GPU culling is off.
|
||||
assert!(sim.records.fading() > 0, "none flagged at the end");
|
||||
|
||||
Reference in new issue
Block a user