From 9392decd3502c2d1e00cc0085e3156f82b9dfcf5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 19:23:53 -0600 Subject: [PATCH] Merge branch 'distant-horizons-core-shadow.frustum.culling' --- .../core/pos/DhFrustumBounds.java | 26 +++- .../core/render/RenderBufferHandler.java | 128 ++++++++++++++---- 2 files changed, 124 insertions(+), 30 deletions(-) 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 index b3759c5e2..39e4234ac 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java @@ -12,25 +12,36 @@ 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 float worldMinY; + public float worldMaxY; - public DhFrustumBounds(Matrix4fc matWorldViewProjection, float minY, float maxY) + //=============// + // constructor // + //=============// + + public DhFrustumBounds() { this.frustum = new FrustumIntersection(); + } + + + + //=========// + // methods // + //=========// + + public void updateFrustum(Matrix4fc matWorldViewProjection) + { 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) + public boolean intersects(@NotNull DhLodPos lodBounds) { int lodPosX = lodBounds.getX().toBlockWidth(); int lodPosZ = lodBounds.getZ().toBlockWidth(); @@ -45,4 +56,5 @@ public class DhFrustumBounds 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 49fcb928f..c89b85e19 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 @@ -21,6 +21,7 @@ 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.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; @@ -32,6 +33,7 @@ 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.wrapperInterfaces.modAccessor.IIrisAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.Logger; @@ -50,6 +52,8 @@ public class RenderBufferHandler implements AutoCloseable { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class); + /** contains all relevant data */ public final LodQuadTree lodQuadTree; @@ -58,7 +62,14 @@ public class RenderBufferHandler implements AutoCloseable private final AtomicBoolean rebuildAllBuffers = new AtomicBoolean(false); - public F3Screen.DynamicMessage f3Message; + public F3Screen.MultiDynamicMessage f3Message; + + private final DhFrustumBounds frustumBounds; + + private int visibleBufferCount; + private int culledBufferCount; + private int shadowVisibleBufferCount; + private int shadowCulledBufferCount; @@ -69,17 +80,43 @@ public class RenderBufferHandler implements AutoCloseable public RenderBufferHandler(LodQuadTree lodQuadTree) { this.lodQuadTree = lodQuadTree; + this.culledBufferCount = 0; - this.f3Message = new F3Screen.DynamicMessage(() -> - { - // should never be null, but just in case something goes wrong, then the F3 menu won't break - String countText = (this.loadedNearToFarBuffers != null) ? this.loadedNearToFarBuffers.size()+"" : "NULL"; - return LodUtil.formatLog("Rendered Buffer Count: " + countText); + this.frustumBounds = new DhFrustumBounds(); + + this.f3Message = new F3Screen.MultiDynamicMessage( + () -> + { + String countText = this.visibleBufferCount + ""; + if (!Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get()) + { + countText += "/" + (this.visibleBufferCount + this.culledBufferCount); + } + return LodUtil.formatLog("Rendered Buffer Count: " + countText); + }, + () -> + { + boolean hasIrisShaders = (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isShaderPackInUse()); + if (!hasIrisShaders) + { + return null; + } + + String countText = this.shadowVisibleBufferCount + ""; + if (!Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get()) + { + countText += "/" + (this.shadowVisibleBufferCount + this.shadowCulledBufferCount); + } + return LodUtil.formatLog("Shadow Buffer Count: " + countText); }); } + //=================// + // render building // + //=================// + /** * The following buildRenderList sorting method is based on the following reddit post:
* correct_depth_ordering_for_translucent_discrete

@@ -188,16 +225,39 @@ public class RenderBufferHandler implements AutoCloseable return loadedBufferA.pos.getDetailLevel() - loadedBufferB.pos.getDetailLevel(); // If all else fails, sort by detail }; - - // 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 + + // update the frustum if necessary + boolean enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); + if (enableFrustumCulling) + { + float worldMinY = clientLevelWrapper.getMinHeight(); + float worldHeight = clientLevelWrapper.getHeight(); + + this.frustumBounds.worldMinY = worldMinY; + this.frustumBounds.worldMaxY = worldMinY + worldHeight; + + this.frustumBounds.updateFrustum(matWorldViewProjection); + } + + + + //=========================// + // Update the section list // + //=========================// + + boolean isShadowPass = (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass()); + if (isShadowPass) + { + this.shadowCulledBufferCount = 0; + } + else + { + this.culledBufferCount = 0; + } + boolean rebuildAllBuffers = this.rebuildAllBuffers.getAndSet(false); Iterator> nodeIterator = this.lodQuadTree.nodeIterator(); while (nodeIterator.hasNext()) @@ -213,10 +273,22 @@ public class RenderBufferHandler implements AutoCloseable try { - DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); - if (enableFrustumCulling && !frustumBounds.Intersects(lodBounds)) + if (enableFrustumCulling) { - continue; + DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); + if (!this.frustumBounds.intersects(lodBounds)) + { + if (isShadowPass) + { + this.shadowCulledBufferCount++; + } + else + { + this.culledBufferCount++; + } + + continue; + } } if (rebuildAllBuffers) @@ -245,16 +317,31 @@ public class RenderBufferHandler implements AutoCloseable renderSection.markBufferDirty(); } } + + if (isShadowPass) + { + this.shadowVisibleBufferCount = this.loadedNearToFarBuffers.size(); + } + else + { + this.visibleBufferCount = this.loadedNearToFarBuffers.size(); + } } + public void MarkAllBuffersDirty() { this.rebuildAllBuffers.set(true); } + + + + //================// + // render methods // + //================// + public void renderOpaque(LodRenderer renderContext, DhApiRenderParam renderEventParam) { - //TODO: Directional culling this.loadedNearToFarBuffers.forEach(loadedBuffer -> loadedBuffer.buffer.renderOpaque(renderContext, renderEventParam)); } public void renderTransparent(LodRenderer renderContext, DhApiRenderParam renderEventParam) { - //TODO: Directional culling ListIterator iter = this.loadedNearToFarBuffers.listIterator(this.loadedNearToFarBuffers.size()); while (iter.hasPrevious()) { @@ -263,11 +350,6 @@ public class RenderBufferHandler implements AutoCloseable } } - public void MarkAllBuffersDirty() - { - rebuildAllBuffers.set(true); - } - //=========//