From 7e287dab713126fad5516c3cf7403881aab155cb Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 17:46:30 -0500 Subject: [PATCH] add frustum culling --- .../core/pos/DhFrustumBounds.java | 37 ++++++++++++++++++ .../core/render/RenderBufferHandler.java | 38 +++++++++++-------- .../core/render/renderer/LodRenderer.java | 16 +++++++- 3 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java 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..70a2be8d4 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java @@ -0,0 +1,37 @@ +package com.seibel.distanthorizons.core.pos; + +import org.joml.Math; +import org.joml.Matrix4f; +import org.joml.Vector3f; + +public class DhFrustumBounds +{ + private final Vector3f boundsMin = new Vector3f(); + private final Vector3f boundsMax = new Vector3f(); + + + public DhFrustumBounds(Matrix4f matViewProjectionInv) + { + matViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); + } + + public boolean Intersects(DhLodPos lodBounds) + { + // TODO + float worldMinY = 0f; + float worldMaxY = 0f; + + int lodPosX = lodBounds.getX().toBlockWidth(); + int lodPosZ = lodBounds.getZ().toBlockWidth(); + int lodSize = lodBounds.getBlockWidth(); + + Vector3f lodMin = new Vector3f(lodPosX, worldMinY, lodPosZ); + Vector3f lodMax = new Vector3f(lodPosX + lodSize, worldMaxY, lodPosZ + lodSize); + + if (lodMax.x < boundsMin.x || lodMin.x > boundsMax.x) return false; + //if (lodMax.y < boundsMin.y || lodMin.y > boundsMax.y) return false; + if (lodMax.z < boundsMin.z || lodMin.z > boundsMax.z) return false; + + return true; + } +} 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 f355d4d4a..cd19f38b6 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 @@ -23,14 +23,19 @@ 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.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.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.Logger; +import org.joml.Matrix4f; +import org.joml.Vector3f; 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(Matrix4f matViewProjectionInv, Vector3f lookForwardVector) { EDhDirection[] axisDirections = new EDhDirection[3]; @@ -187,6 +192,8 @@ 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? + DhFrustumBounds frustumBounds = new DhFrustumBounds(matViewProjectionInv); + // Update the sections boolean rebuildAllBuffers = this.rebuildAllBuffers.getAndSet(false); Iterator> nodeIterator = this.lodQuadTree.nodeIterator(); @@ -196,26 +203,25 @@ public class RenderBufferHandler implements AutoCloseable DhSectionPos sectionPos = node.sectionPos; LodRenderSection renderSection = node.value; + if (renderSection == null) continue; + try { + DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); + if (!frustumBounds.Intersects(lodBounds)) continue; - if (renderSection != null) + if (rebuildAllBuffers) { - if (rebuildAllBuffers) - { - renderSection.markBufferDirty(); - } - renderSection.tryBuildAndSwapBuffer(); - - if (renderSection.isRenderingEnabled()) - { - AbstractRenderBuffer buffer = renderSection.activeRenderBufferRef.get(); - if (buffer != null) - { - this.loadedNearToFarBuffers.add(new LoadedRenderBuffer(buffer, sectionPos)); - } - } + 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 de8824a5e..df82adcf5 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 @@ -47,6 +47,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.Vector3f; import org.lwjgl.opengl.GL32; import java.awt.*; @@ -330,7 +332,19 @@ public class LodRenderer if (renderingFirstPass) { - this.bufferHandler.buildRenderListAndUpdateSections(this.getLookVector()); + final Vector3f WorldUp = new Vector3f(0f, 1f, 0f); + + Vec3f _lookAt = this.getLookVector(); + Vector3f lookAt = new Vector3f(_lookAt.x, _lookAt.y, _lookAt.z); + Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); + + Matrix4f matViewProjectionInv = new Matrix4f() + .setTransposed(projectionMatrix.getValuesAsArray()) + .lookAlong(lookAt, WorldUp) + .translate(-(float)cameraPos.x, -(float)cameraPos.y, -(float)cameraPos.z) + .invert(); + + this.bufferHandler.buildRenderListAndUpdateSections(matViewProjectionInv, lookAt); transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled;