Skip to content

Commit 9c44397

Browse files
committed
add region sorting to fix translucency sorting issues,
tree traversal only does correct in-region sorting, not between regions
1 parent 816bde2 commit 9c44397

File tree

6 files changed

+89
-48
lines changed

6 files changed

+89
-48
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ private void processRenderListUpdate(Viewport viewport) {
423423
this.renderableSectionTree.prepareForTraversal();
424424
this.renderableSectionTree.traverse(visitor, viewport, searchDistance);
425425

426-
this.renderLists = visitor.createRenderLists();
426+
this.renderLists = visitor.createRenderLists(viewport);
427427
this.frustumTaskLists = visitor.getPendingTaskLists();
428428
this.globalTaskLists = null;
429429
this.renderTree = null;
@@ -432,7 +432,7 @@ private void processRenderListUpdate(Viewport viewport) {
432432

433433
var visibleCollector = new VisibleChunkCollectorAsync(this.regions, this.frame);
434434
bestTree.traverse(visibleCollector, viewport, this.getSearchDistance());
435-
this.renderLists = visibleCollector.createRenderLists();
435+
this.renderLists = visibleCollector.createRenderLists(viewport);
436436

437437
var end = System.nanoTime();
438438
var time = end - start;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public FallbackVisibleChunkCollector(Viewport viewport, float buildDistance, Lon
1313
this.renderListCollector = new VisibleChunkCollectorAsync(regions, frame);
1414
}
1515

16-
public SortedRenderLists createRenderLists() {
17-
return this.renderListCollector.createRenderLists();
16+
public SortedRenderLists createRenderLists(Viewport viewport) {
17+
return this.renderListCollector.createRenderLists(viewport);
1818
}
1919

2020
@Override
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package net.caffeinemc.mods.sodium.client.render.chunk.lists;
2+
3+
import it.unimi.dsi.fastutil.ints.IntArrays;
4+
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
5+
import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegion;
6+
import net.caffeinemc.mods.sodium.client.render.viewport.Viewport;
7+
8+
public interface RenderListProvider {
9+
ObjectArrayList<ChunkRenderList> getUnsortedRenderLists();
10+
11+
int[] getCachedSortItems();
12+
13+
void setCachedSortItems(int[] sortItems);
14+
15+
default SortedRenderLists createRenderLists(Viewport viewport) {
16+
// sort the regions by distance to fix rare region ordering bugs
17+
var sectionPos = viewport.getChunkCoord();
18+
var cameraX = sectionPos.getX() >> RenderRegion.REGION_WIDTH_SH;
19+
var cameraY = sectionPos.getY() >> RenderRegion.REGION_HEIGHT_SH;
20+
var cameraZ = sectionPos.getZ() >> RenderRegion.REGION_LENGTH_SH;
21+
22+
var unsortedRenderLists = this.getUnsortedRenderLists();
23+
var size = unsortedRenderLists.size();
24+
25+
var sortItems = this.getCachedSortItems();
26+
if (sortItems.length < size) {
27+
sortItems = new int[size];
28+
this.setCachedSortItems(sortItems);
29+
}
30+
31+
for (var i = 0; i < size; i++) {
32+
var region = unsortedRenderLists.get(i).getRegion();
33+
var x = Math.abs(region.getX() - cameraX);
34+
var y = Math.abs(region.getY() - cameraY);
35+
var z = Math.abs(region.getZ() - cameraZ);
36+
sortItems[i] = (x + y + z) << 16 | i;
37+
}
38+
39+
IntArrays.unstableSort(sortItems, 0, size);
40+
41+
var sorted = new ObjectArrayList<ChunkRenderList>(size);
42+
for (var i = 0; i < size; i++) {
43+
var key = sortItems[i];
44+
var renderList = unsortedRenderLists.get(key & 0xFFFF);
45+
sorted.add(renderList);
46+
}
47+
48+
for (var list : sorted) {
49+
list.sortSections(sectionPos, sortItems);
50+
}
51+
52+
return new SortedRenderLists(sorted);
53+
}
54+
}

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

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

3-
import it.unimi.dsi.fastutil.ints.IntArrays;
43
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
54
import net.caffeinemc.mods.sodium.client.render.chunk.LocalSectionIndex;
65
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.SectionTree;
76
import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegion;
87
import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegionManager;
9-
import net.caffeinemc.mods.sodium.client.render.viewport.Viewport;
10-
11-
import java.util.ArrayDeque;
12-
import java.util.EnumMap;
13-
import java.util.Map;
14-
import java.util.Queue;
158

169
/**
1710
* The async visible chunk collector is passed into a section tree to collect visible chunks.
1811
*/
19-
public class VisibleChunkCollectorAsync implements SectionTree.VisibleSectionVisitor {
12+
public class VisibleChunkCollectorAsync implements SectionTree.VisibleSectionVisitor, RenderListProvider {
2013
private final RenderRegionManager regions;
2114
private final int frame;
2215

@@ -55,7 +48,20 @@ public void visit(int x, int y, int z) {
5548
renderList.add(sectionIndex);
5649
}
5750

58-
public SortedRenderLists createRenderLists() {
59-
return new SortedRenderLists(this.sortedRenderLists);
51+
private static int[] sortItems = new int[RenderRegion.REGION_SIZE];
52+
53+
@Override
54+
public ObjectArrayList<ChunkRenderList> getUnsortedRenderLists() {
55+
return this.sortedRenderLists;
56+
}
57+
58+
@Override
59+
public int[] getCachedSortItems() {
60+
return sortItems;
61+
}
62+
63+
@Override
64+
public void setCachedSortItems(int[] sortItems) {
65+
VisibleChunkCollectorAsync.sortItems = sortItems;
6066
}
6167
}
Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package net.caffeinemc.mods.sodium.client.render.chunk.lists;
22

3-
import it.unimi.dsi.fastutil.ints.IntArrays;
43
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
54
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
65
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionFlags;
@@ -13,7 +12,7 @@
1312
/**
1413
* The sync visible chunk collector is passed into the graph search occlusion culler to collect visible chunks.
1514
*/
16-
public class VisibleChunkCollectorSync extends SectionTree {
15+
public class VisibleChunkCollectorSync extends SectionTree implements RenderListProvider {
1716
private final ObjectArrayList<ChunkRenderList> sortedRenderLists;
1817

1918
public VisibleChunkCollectorSync(Viewport viewport, float buildDistance, int frame, CullType cullType, Level level) {
@@ -44,39 +43,18 @@ public void visit(RenderSection section) {
4443

4544
private static int[] sortItems = new int[RenderRegion.REGION_SIZE];
4645

47-
public SortedRenderLists createRenderLists(Viewport viewport) {
48-
// sort the regions by distance to fix rare region ordering bugs
49-
var sectionPos = viewport.getChunkCoord();
50-
var cameraX = sectionPos.getX() >> RenderRegion.REGION_WIDTH_SH;
51-
var cameraY = sectionPos.getY() >> RenderRegion.REGION_HEIGHT_SH;
52-
var cameraZ = sectionPos.getZ() >> RenderRegion.REGION_LENGTH_SH;
53-
var size = this.sortedRenderLists.size();
54-
55-
if (sortItems.length < size) {
56-
sortItems = new int[size];
57-
}
58-
59-
for (var i = 0; i < size; i++) {
60-
var region = this.sortedRenderLists.get(i).getRegion();
61-
var x = Math.abs(region.getX() - cameraX);
62-
var y = Math.abs(region.getY() - cameraY);
63-
var z = Math.abs(region.getZ() - cameraZ);
64-
sortItems[i] = (x + y + z) << 16 | i;
65-
}
66-
67-
IntArrays.unstableSort(sortItems, 0, size);
68-
69-
var sorted = new ObjectArrayList<ChunkRenderList>(size);
70-
for (var i = 0; i < size; i++) {
71-
var key = sortItems[i];
72-
var renderList = this.sortedRenderLists.get(key & 0xFFFF);
73-
sorted.add(renderList);
74-
}
46+
@Override
47+
public ObjectArrayList<ChunkRenderList> getUnsortedRenderLists() {
48+
return this.sortedRenderLists;
49+
}
7550

76-
for (var list : sorted) {
77-
list.sortSections(sectionPos, sortItems);
78-
}
51+
@Override
52+
public int[] getCachedSortItems() {
53+
return sortItems;
54+
}
7955

80-
return new SortedRenderLists(sorted);
56+
@Override
57+
public void setCachedSortItems(int[] sortItems) {
58+
VisibleChunkCollectorSync.sortItems = sortItems;
8159
}
8260
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import net.caffeinemc.mods.sodium.client.render.viewport.Viewport;
66
import org.joml.FrustumIntersection;
77

8+
/**
9+
* A traversable tree is a tree of sections that can be traversed with a distance limit and a frustum. It traverses the sections in visual front-to-back order, so that they can be directly put into a render list. Note however that ordering regions by adding them to the list the first time one of their sections is visited does not yield the correct order. This is because the sections are traversed in visual order, not ordered by distance from the camera.
10+
*/
811
public class TraversableTree extends Tree {
912
private static final int INSIDE_FRUSTUM = 0b01;
1013
private static final int INSIDE_DISTANCE = 0b10;

0 commit comments

Comments
 (0)