Skip to content

Commit bb5c435

Browse files
committed
fix #2266 by sorting regions after render list generation
1 parent 24f77ee commit bb5c435

File tree

5 files changed

+48
-54
lines changed

5 files changed

+48
-54
lines changed

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ public RenderSection(RenderRegion region, int chunkX, int chunkY, int chunkZ) {
6969
this.chunkY = chunkY;
7070
this.chunkZ = chunkZ;
7171

72-
int rX = this.getChunkX() & (RenderRegion.REGION_WIDTH - 1);
73-
int rY = this.getChunkY() & (RenderRegion.REGION_HEIGHT - 1);
74-
int rZ = this.getChunkZ() & (RenderRegion.REGION_LENGTH - 1);
72+
int rX = this.getChunkX() & RenderRegion.REGION_WIDTH_M;
73+
int rY = this.getChunkY() & RenderRegion.REGION_HEIGHT_M;
74+
int rZ = this.getChunkZ() & RenderRegion.REGION_LENGTH_M;
7575

7676
this.sectionIndex = LocalSectionIndex.pack(rX, rY, rZ);
7777

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ private void createTerrainRenderList(Camera camera, Viewport viewport, int frame
146146

147147
this.occlusionCuller.findVisible(visitor, viewport, searchDistance, useOcclusionCulling, frame);
148148

149-
this.renderLists = visitor.createRenderLists();
149+
this.renderLists = visitor.createRenderLists(viewport);
150150
this.taskLists = visitor.getRebuildLists();
151151
}
152152

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package net.caffeinemc.mods.sodium.client.render.chunk.lists;
22

33
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
4-
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
54
import net.caffeinemc.mods.sodium.client.util.iterator.ReversibleObjectArrayIterator;
6-
import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegion;
75

86
/**
97
* Stores one render list of sections per region, sorted by the order in which
@@ -27,44 +25,4 @@ public ReversibleObjectArrayIterator<ChunkRenderList> iterator(boolean reverse)
2725
public static SortedRenderLists empty() {
2826
return EMPTY;
2927
}
30-
31-
public static class Builder {
32-
private final ObjectArrayList<ChunkRenderList> lists = new ObjectArrayList<>();
33-
private final int frame;
34-
35-
public Builder(int frame) {
36-
this.frame = frame;
37-
}
38-
39-
public void add(RenderSection section) {
40-
RenderRegion region = section.getRegion();
41-
ChunkRenderList list = region.getRenderList();
42-
43-
// Even if a section does not have render objects, we must ensure the render list is initialized and put
44-
// into the sorted queue of lists, so that we maintain the correct order of draw calls.
45-
if (list.getLastVisibleFrame() != this.frame) {
46-
list.reset(this.frame);
47-
48-
this.lists.add(list);
49-
}
50-
51-
// Only add the section to the render list if it actually contains render objects
52-
if (section.getFlags() != 0) {
53-
list.add(section);
54-
}
55-
}
56-
57-
public SortedRenderLists build() {
58-
var filtered = new ObjectArrayList<ChunkRenderList>(this.lists.size());
59-
60-
// Filter any empty render lists
61-
for (var list : this.lists) {
62-
if (list.size() > 0) {
63-
filtered.add(list);
64-
}
65-
}
66-
67-
return new SortedRenderLists(filtered);
68-
}
69-
}
7028
}

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/VisibleChunkCollector.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
66
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.OcclusionCuller;
77
import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegion;
8+
import net.caffeinemc.mods.sodium.client.render.viewport.Viewport;
89

910
import java.util.*;
1011

@@ -61,8 +62,31 @@ private void addToRebuildLists(RenderSection section) {
6162
}
6263
}
6364

64-
public SortedRenderLists createRenderLists() {
65-
return new SortedRenderLists(this.sortedRenderLists);
65+
public SortedRenderLists createRenderLists(Viewport viewport) {
66+
// sort the regions by distance to fix rare region ordering bugs
67+
var transform = viewport.getTransform();
68+
var cameraX = transform.intX >> (4 + RenderRegion.REGION_WIDTH_SH);
69+
var cameraY = transform.intY >> (4 + RenderRegion.REGION_HEIGHT_SH);
70+
var cameraZ = transform.intZ >> (4 + RenderRegion.REGION_LENGTH_SH);
71+
var size = this.sortedRenderLists.size();
72+
73+
var items = new int[size];
74+
for (var i = 0; i < size; i++) {
75+
var region = this.sortedRenderLists.get(i).getRegion();
76+
var x = Math.abs(region.getRawX() - cameraX);
77+
var y = Math.abs(region.getRawY() - cameraY);
78+
var z = Math.abs(region.getRawZ() - cameraZ);
79+
items[i] = (x + y + z) << 16 | i;
80+
}
81+
82+
Arrays.sort(items);
83+
84+
var sorted = new ObjectArrayList<ChunkRenderList>(size);
85+
for (var key : items) {
86+
sorted.add(this.sortedRenderLists.get(key & 0xFFFF));
87+
}
88+
89+
return new SortedRenderLists(sorted);
6690
}
6791

6892
public Map<ChunkUpdateType, ArrayDeque<RenderSection>> getRebuildLists() {

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegion.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ public class RenderRegion {
2424
public static final int REGION_HEIGHT = 4;
2525
public static final int REGION_LENGTH = 8;
2626

27-
private static final int REGION_WIDTH_M = RenderRegion.REGION_WIDTH - 1;
28-
private static final int REGION_HEIGHT_M = RenderRegion.REGION_HEIGHT - 1;
29-
private static final int REGION_LENGTH_M = RenderRegion.REGION_LENGTH - 1;
27+
public static final int REGION_WIDTH_M = RenderRegion.REGION_WIDTH - 1;
28+
public static final int REGION_HEIGHT_M = RenderRegion.REGION_HEIGHT - 1;
29+
public static final int REGION_LENGTH_M = RenderRegion.REGION_LENGTH - 1;
3030

31-
protected static final int REGION_WIDTH_SH = Integer.bitCount(REGION_WIDTH_M);
32-
protected static final int REGION_HEIGHT_SH = Integer.bitCount(REGION_HEIGHT_M);
33-
protected static final int REGION_LENGTH_SH = Integer.bitCount(REGION_LENGTH_M);
31+
public static final int REGION_WIDTH_SH = Integer.bitCount(REGION_WIDTH_M);
32+
public static final int REGION_HEIGHT_SH = Integer.bitCount(REGION_HEIGHT_M);
33+
public static final int REGION_LENGTH_SH = Integer.bitCount(REGION_LENGTH_M);
3434

3535
public static final int REGION_SIZE = REGION_WIDTH * REGION_HEIGHT * REGION_LENGTH;
3636

@@ -64,6 +64,18 @@ public static long key(int x, int y, int z) {
6464
return SectionPos.asLong(x, y, z);
6565
}
6666

67+
public int getRawX() {
68+
return this.x;
69+
}
70+
71+
public int getRawY() {
72+
return this.y;
73+
}
74+
75+
public int getRawZ() {
76+
return this.z;
77+
}
78+
6779
public int getChunkX() {
6880
return this.x << REGION_WIDTH_SH;
6981
}

0 commit comments

Comments
 (0)