When i press F3+A (reload chunks) or teleport to a new area, the chunks around me first show as big low quality squares, then slowly refine to the real detail over a couple seconds. Its very distracting to look at, specialy on big render distance.
Related maybe: #356
I dig into the code a bit and i think its coming from few things stacking together.
1. RenderDistanceTracker.java only process 40 ring cells per frame, no matter how big the backlog is:
return this.tracker.process(this.processRate, this::add, this::rem)!=0;
After a reload the whole visible ring need to get requested at once (from MixinLevelExtractor.java, which shutdown and recreate the whole render system on allChanged, so the octree start from nothing again), but only 40 cells get queued per frame, so it take many frames just to even ask for the top level nodes.
2. In traversal_dev.comp, when a node want more detail (subdivide) but its children request isnt finished, it still draw itself as a fallback, no matter how oversized it look for how close it is:
if (shouldRenderSelf) {
enqueueSelfForRender(node);
}
This is what make the big low-res squares show up, they just havent got their children mesh yet.
I try some fixes on my own copy:
- burst the ring processing rate when there is a big backlog (based on
pendingCount() i added to RingTracker), instead of always 40/frame
- dont draw the fallback node self mesh if its screen size is way past the target detail size (
MAX_COARSE_POP_RATIO), so it wait a bit instead of flashing a giant square
It help a lot but the popping effect is still kinda visible sometimes, specialy with high render distance. I think the full fix probably need something like cross-fade between LOD levels, or not fully destroying the node manager/octree on reload (only re-validate whats needed).
Happy to share the diff if it help, just wanted to report the root cause first in case there is already a reason things work this way that i dont know about.
When i press F3+A (reload chunks) or teleport to a new area, the chunks around me first show as big low quality squares, then slowly refine to the real detail over a couple seconds. Its very distracting to look at, specialy on big render distance.
Related maybe: #356
I dig into the code a bit and i think its coming from few things stacking together.
1.
RenderDistanceTracker.javaonly process 40 ring cells per frame, no matter how big the backlog is:After a reload the whole visible ring need to get requested at once (from
MixinLevelExtractor.java, which shutdown and recreate the whole render system onallChanged, so the octree start from nothing again), but only 40 cells get queued per frame, so it take many frames just to even ask for the top level nodes.2. In
traversal_dev.comp, when a node want more detail (subdivide) but its children request isnt finished, it still draw itself as a fallback, no matter how oversized it look for how close it is:if (shouldRenderSelf) { enqueueSelfForRender(node); }This is what make the big low-res squares show up, they just havent got their children mesh yet.
I try some fixes on my own copy:
pendingCount()i added toRingTracker), instead of always 40/frameMAX_COARSE_POP_RATIO), so it wait a bit instead of flashing a giant squareIt help a lot but the popping effect is still kinda visible sometimes, specialy with high render distance. I think the full fix probably need something like cross-fade between LOD levels, or not fully destroying the node manager/octree on reload (only re-validate whats needed).
Happy to share the diff if it help, just wanted to report the root cause first in case there is already a reason things work this way that i dont know about.