Skip to content

Commit

Permalink
Use the same view distance culling formula as vanilla
Browse files Browse the repository at this point in the history
This also adjusts fog occlusion culling to create an
"effective view distance" which is used in place of
more expensive checks.
  • Loading branch information
jellysquid3 committed Jul 23, 2023
1 parent bc1fbf9 commit a04ce05
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,32 +177,22 @@ public float getSquaredDistance(float x, float y, float z) {
/**
* @return The x-coordinate of the center position of this chunk render
*/
private float getCenterX() {
return this.getOriginX() + 8.0f;
private int getCenterX() {
return this.getOriginX() + 8;
}

/**
* @return The y-coordinate of the center position of this chunk render
*/
private float getCenterY() {
return this.getOriginY() + 8.0f;
private int getCenterY() {
return this.getOriginY() + 8;
}

/**
* @return The z-coordinate of the center position of this chunk render
*/
private float getCenterZ() {
return this.getOriginZ() + 8.0f;
}

/**
* @return The squared distance from the center of this chunk in the world to the given position
*/
public float getSquaredDistanceXZ(float x, float z) {
float xDist = x - this.getCenterX();
float zDist = z - this.getCenterZ();

return (xDist * xDist) + (zDist * zDist);
private int getCenterZ() {
return this.getOriginZ() + 8;
}

public int getChunkX() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,6 @@ public class RenderSectionManager {
*/
private static final double NEARBY_CHUNK_DISTANCE = Math.pow(32, 2.0);

/**
* The minimum distance the culling plane can be from the player's camera. This helps to prevent mathematical
* errors that occur when the fog distance is less than 8 blocks in width, such as when using a blindness potion.
*/
private static final float FOG_PLANE_MIN_DISTANCE = (float) Math.pow(8.0f, 2.0);

/**
* The distance past the fog's far plane at which to begin culling. Distance calculations use the center of each
* chunk from the camera's position, and as such, special care is needed to ensure that the culling plane is pushed
* back far enough. I'm sure there's a mathematical formula that should be used here in place of the constant,
* but this value works fine in testing.
*/
private static final float FOG_PLANE_OFFSET = 12.0f;

private final ChunkBuilder builder;

private final RenderRegionManager regions;
Expand All @@ -83,17 +69,15 @@ public class RenderSectionManager {
private final ClientWorld world;

private final int renderDistance;
private int effectiveRenderDistance;

private float cameraX, cameraY, cameraZ;
private int centerChunkX, centerChunkZ;
private int centerChunkX, centerChunkY, centerChunkZ;

private boolean needsUpdate;

private boolean useFogCulling;
private boolean useOcclusionCulling;

private float fogRenderCutoff;

private Frustum frustum;

private int currentFrame = 0;
Expand Down Expand Up @@ -151,18 +135,7 @@ private void setup(Camera camera) {

var options = SodiumClientMod.options();

this.useFogCulling = options.performance.useFogOcclusion;
this.alwaysDeferChunkUpdates = options.performance.alwaysDeferChunkUpdates;

if (this.useFogCulling) {
float dist = RenderSystem.getShaderFogEnd() + FOG_PLANE_OFFSET;

if (dist == 0.0f) {
this.fogRenderCutoff = Float.POSITIVE_INFINITY;
} else {
this.fogRenderCutoff = Math.max(FOG_PLANE_MIN_DISTANCE, dist * dist);
}
}
}

private void iterateChunks(ChunkRenderListBuilder list, Camera camera, Frustum frustum, int frame, boolean spectator) {
Expand Down Expand Up @@ -494,9 +467,10 @@ public void onChunkRenderUpdates(int x, int y, int z, ChunkRenderData data) {

private boolean isWithinRenderDistance(RenderSection adj) {
int x = Math.abs(adj.getChunkX() - this.centerChunkX);
int y = Math.abs(adj.getChunkY() - this.centerChunkY);
int z = Math.abs(adj.getChunkZ() - this.centerChunkZ);

return x <= this.renderDistance && z <= this.renderDistance;
return Math.max(x, Math.max(y, z)) <= this.effectiveRenderDistance;
}

private boolean isCulled(RenderSection section, Direction from, Direction to) {
Expand All @@ -512,6 +486,12 @@ private void initSearch(ChunkRenderListBuilder list, Camera camera, Frustum frus
this.frustum = frustum;
this.useOcclusionCulling = MinecraftClient.getInstance().chunkCullingEnabled;

if (SodiumClientMod.options().performance.useFogOcclusion) {
this.effectiveRenderDistance = Math.min(this.getEffectiveViewDistance(), this.renderDistance);
} else {
this.effectiveRenderDistance = this.renderDistance;
}

this.iterationQueue.clear();

BlockPos origin = camera.getBlockPos();
Expand All @@ -521,6 +501,7 @@ private void initSearch(ChunkRenderListBuilder list, Camera camera, Frustum frus
int chunkZ = origin.getZ() >> 4;

this.centerChunkX = chunkX;
this.centerChunkY = chunkY;
this.centerChunkZ = chunkZ;

RenderSection rootRender = this.getRenderSection(chunkX, chunkY, chunkZ);
Expand All @@ -539,8 +520,8 @@ private void initSearch(ChunkRenderListBuilder list, Camera camera, Frustum frus

List<RenderSection> sorted = new ArrayList<>();

for (int x2 = -this.renderDistance; x2 <= this.renderDistance; ++x2) {
for (int z2 = -this.renderDistance; z2 <= this.renderDistance; ++z2) {
for (int x2 = -this.effectiveRenderDistance; x2 <= this.effectiveRenderDistance; ++x2) {
for (int z2 = -this.effectiveRenderDistance; z2 <= this.effectiveRenderDistance; ++z2) {
RenderSection render = this.getRenderSection(chunkX + x2, chunkY, chunkZ + z2);

if (render == null || render.isCulledByFrustum(frustum)) {
Expand All @@ -562,6 +543,18 @@ private void initSearch(ChunkRenderListBuilder list, Camera camera, Frustum frus
}
}

private int getEffectiveViewDistance() {
var color = RenderSystem.getShaderFogColor();
var distance = RenderSystem.getShaderFogEnd();

// The fog must be fully opaque in order to skip rendering of chunks behind it
if (!MathHelper.approximatelyEquals(color[3], 1.0f)) {
return this.renderDistance;
}

return MathHelper.floor(distance) >> 4;
}


private void bfsEnqueue(ChunkRenderListBuilder list, RenderSection parent, RenderSection render, Direction flow) {
if (render.getLastVisibleFrame() == this.currentFrame) {
Expand All @@ -581,10 +574,6 @@ private void bfsEnqueue(ChunkRenderListBuilder list, RenderSection parent, Rende
private void addVisible(ChunkRenderListBuilder list, RenderSection render, Direction flow) {
this.iterationQueue.add(render, flow);

if (this.useFogCulling && render.getSquaredDistanceXZ(this.cameraX, this.cameraZ) >= this.fogRenderCutoff) {
return;
}

int flags = render.getFlags();

if ((flags & RenderSectionFlags.HAS_BLOCK_GEOMETRY) != 0) {
Expand Down

0 comments on commit a04ce05

Please sign in to comment.