diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index e6d971141..a24224c74 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -533,18 +533,17 @@ public class Config public static class AdvancedGraphics { - // TODO re-implement -// public static ConfigEntry disableDirectionalCulling = new ConfigEntry.Builder() -// .set(false) -// .comment("" -// + "If false fake chunks behind the player's camera \n" -// + "aren't drawn, increasing GPU performance. \n" -// + "\n" -// + "If true all LODs are drawn, even those behind \n" -// + "the player's camera, decreasing GPU performance. \n" -// + "\n" -// + "Disable this if you see LODs disappearing at the corners of your vision.") -// .build(); + public static ConfigEntry disableFrustumCulling = new ConfigEntry.Builder() + .set(false) + .comment("" + + "If false LODs outside the player's camera \n" + + "aren't drawn, increasing GPU performance. \n" + + "\n" + + "If true all LODs are drawn, even those behind \n" + + "the player's camera, decreasing GPU performance. \n" + + "\n" + + "Disable this if you see LODs disappearing at the corners of your vision.") + .build(); /** * @deprecated Use overdrawPrevention instead, will be removed when DH updates to MC 1.21
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java new file mode 100644 index 000000000..b3759c5e2 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java @@ -0,0 +1,48 @@ +package com.seibel.distanthorizons.core.pos; + +import org.jetbrains.annotations.NotNull; +import org.joml.FrustumIntersection; +import org.joml.Matrix4f; +import org.joml.Matrix4fc; +import org.joml.Vector3f; + + +public class DhFrustumBounds +{ + private final FrustumIntersection frustum; + private final Vector3f boundsMin = new Vector3f(); + private final Vector3f boundsMax = new Vector3f(); + private final float worldMinY; + private final float worldMaxY; + + + + public DhFrustumBounds(Matrix4fc matWorldViewProjection, float minY, float maxY) + { + this.frustum = new FrustumIntersection(); + this.frustum.set(matWorldViewProjection); + + Matrix4fc matWorldViewProjectionInv = new Matrix4f(matWorldViewProjection).invert(); + matWorldViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); + + this.worldMinY = minY; + this.worldMaxY = maxY; + } + + /** returns true if the LOD bounds intersect the frustum **/ + public boolean Intersects(@NotNull DhLodPos lodBounds) + { + int lodPosX = lodBounds.getX().toBlockWidth(); + int lodPosZ = lodBounds.getZ().toBlockWidth(); + int lodSize = lodBounds.getBlockWidth(); + + Vector3f lodMin = new Vector3f(lodPosX, this.worldMinY, lodPosZ); + Vector3f lodMax = new Vector3f(lodPosX + lodSize, this.worldMaxY, lodPosZ + lodSize); + + if (lodMax.x < this.boundsMin.x || lodMin.x > this.boundsMax.x) return false; + if (lodMax.z < this.boundsMin.z || lodMin.z > this.boundsMax.z) return false; + if (this.worldMaxY < this.boundsMin.y || this.worldMinY > this.boundsMax.y) return false; + + return this.frustum.testAab(lodMin, lodMax); + } +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 6478ca15f..49fcb928f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -20,17 +20,22 @@ package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; +import com.seibel.distanthorizons.core.pos.DhFrustumBounds; +import com.seibel.distanthorizons.core.pos.DhLodPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.Pos2D; +import com.seibel.distanthorizons.core.render.renderer.LodRenderer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.SortedArraySet; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; -import com.seibel.distanthorizons.core.render.renderer.LodRenderer; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.Logger; +import org.joml.Matrix4fc; import java.util.Comparator; import java.util.Iterator; @@ -82,7 +87,7 @@ public class RenderBufferHandler implements AutoCloseable * TODO: This might get locked by update() causing move() call. Is there a way to avoid this? * Maybe dupe the base list and use atomic swap on render? Or is this not worth it? */ - public void buildRenderListAndUpdateSections(Vec3f lookForwardVector) + public void buildRenderListAndUpdateSections(IClientLevelWrapper clientLevelWrapper, Matrix4fc matWorldViewProjection, Vec3f lookForwardVector) { EDhDirection[] axisDirections = new EDhDirection[3]; @@ -187,6 +192,11 @@ public class RenderBufferHandler implements AutoCloseable // Build the sorted list this.loadedNearToFarBuffers = new SortedArraySet<>((a, b) -> -farToNearComparator.compare(a, b)); // TODO is the comparator named wrong? + float worldMinY = clientLevelWrapper.getMinHeight(); + float worldHeight = clientLevelWrapper.getHeight(); + DhFrustumBounds frustumBounds = new DhFrustumBounds(matWorldViewProjection, worldMinY, worldMinY + worldHeight); + boolean enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); + // Update the sections boolean rebuildAllBuffers = this.rebuildAllBuffers.getAndSet(false); Iterator> nodeIterator = this.lodQuadTree.nodeIterator(); @@ -196,26 +206,38 @@ public class RenderBufferHandler implements AutoCloseable DhSectionPos sectionPos = node.sectionPos; LodRenderSection renderSection = node.value; + if (renderSection == null) + { + continue; + } + try { - - if (renderSection != null) + DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); + if (enableFrustumCulling && !frustumBounds.Intersects(lodBounds)) { - if (rebuildAllBuffers) - { - renderSection.markBufferDirty(); - } - renderSection.tryBuildAndSwapBuffer(); - - if (renderSection.isRenderingEnabled()) - { - AbstractRenderBuffer buffer = renderSection.activeRenderBufferRef.get(); - if (buffer != null) - { - this.loadedNearToFarBuffers.add(new LoadedRenderBuffer(buffer, sectionPos)); - } - } + continue; } + + if (rebuildAllBuffers) + { + renderSection.markBufferDirty(); + } + + renderSection.tryBuildAndSwapBuffer(); + if (!renderSection.isRenderingEnabled()) + { + continue; + } + + AbstractRenderBuffer buffer = renderSection.activeRenderBufferRef.get(); + if (buffer == null) + { + continue; + } + + + this.loadedNearToFarBuffers.add(new LoadedRenderBuffer(buffer, sectionPos)); } catch (Exception e) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 672ec1196..dac8d049b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -57,6 +57,8 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3d; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.LogManager; +import org.joml.Matrix4f; +import org.joml.Matrix4fc; import org.lwjgl.opengl.GL32; import java.awt.*; @@ -349,7 +351,14 @@ public class LodRenderer if (renderingFirstPass) { - this.bufferHandler.buildRenderListAndUpdateSections(MC_RENDER.getLookAtVector()); + Matrix4f matWorldView = new Matrix4f() + .setTransposed(MC_RENDER.getWorldViewMatrix().getValuesAsArray()); + + Matrix4fc matWorldViewProjection = new Matrix4f() + .setTransposed(renderEventParam.dhProjectionMatrix.getValuesAsArray()) + .mul(matWorldView); + + this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matWorldViewProjection, MC_RENDER.getLookAtVector()); transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java index fd0ee2371..42d355520 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java @@ -54,6 +54,8 @@ public interface IMinecraftRenderWrapper extends IBindable Vec3d getCameraExactPosition(); + Mat4f getWorldViewMatrix(); + Mat4f getDefaultProjectionMatrix(float partialTicks); double getGamma(); diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 9b969e90d..3adec012b 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -265,6 +265,10 @@ "distanthorizons.config.client.advanced.graphics.advancedGraphics": "Advanced Graphics Options", + "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableFrustumCulling": + "Disable Frustum Culling", + "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableFrustumCulling.@tooltip": + "If false LODs outside the player's camera \naren't drawn, increasing GPU performance. \n\nIf true all LODs are drawn, even those behind \nthe player's camera, decreasing GPU performance. \n\nDisable this if you see LODs disappearing at the corners of your vision.", "distanthorizons.config.client.advanced.graphics.advancedGraphics.overdrawPrevention": "Overdraw Prevention", "distanthorizons.config.client.advanced.graphics.advancedGraphics.overdrawPrevention.@tooltip":