From 0efa4c3de33b0d2650e0bb99f2e42add066adf6a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jan 2024 19:24:17 -0600 Subject: [PATCH 01/34] Merge branch 'distant-horizons-core-main' --- .../core/api/internal/ClientApi.java | 71 ++- .../distanthorizons/core/config/Config.java | 1 + .../render/ColumnRenderSource.java | 27 +- .../render/bufferBuilding/BufferQuad.java | 13 +- .../render/bufferBuilding/ColumnBox.java | 66 +-- .../bufferBuilding/CubicLodTemplate.java | 10 +- .../render/bufferBuilding/LodQuadBuilder.java | 22 +- .../FullDataToRenderDataTransformer.java | 16 +- .../core/level/ClientLevelModule.java | 14 +- .../core/level/DhClientLevel.java | 8 +- .../core/level/DhClientServerLevel.java | 8 +- .../core/level/IDhClientLevel.java | 1 + .../core/render/AbstractRenderBuffer.java | 5 +- .../core/render/LodRenderSection.java | 3 + .../core/render/RenderBufferHandler.java | 7 +- .../render/renderer/LodRenderProgram.java | 9 +- .../core/render/renderer/LodRenderer.java | 499 +++++++++++------- .../vertexFormat/DefaultLodVertexFormats.java | 22 +- .../distanthorizons/core/util/LodUtil.java | 3 +- .../util/RenderDataPointReducingList.java | 8 +- .../core/util/RenderDataPointUtil.java | 61 +-- .../block/IBlockStateWrapper.java | 2 + 22 files changed, 496 insertions(+), 380 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index 717e9d915..4b53ffc84 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -32,7 +32,6 @@ import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.api.enums.rendering.EDebugRendering; import com.seibel.distanthorizons.api.enums.rendering.ERendererMode; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.SpamReducedLogger; @@ -51,8 +50,6 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; import java.util.concurrent.TimeUnit; @@ -92,6 +89,9 @@ public class ClientApi /** Holds any chunks that were loaded before the {@link ClientApi#clientLevelLoadEvent(IClientLevelWrapper)} was fired. */ public final HashMap, IChunkWrapper> waitingChunkByClientLevelAndPos = new HashMap<>(); + /** re-set every frame during the opaque rendering stage */ + private boolean renderingCancelledForThisFrame; + //==============// @@ -450,21 +450,37 @@ public class ClientApi // rendering // //===========// + /** Should be called before {@link ClientApi#renderDeferredLods} */ public void renderLods(IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks) + { this.renderLodLayer(levelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, true); } + + /** + * Only necessary when Shaders are in use. + * Should be called after {@link ClientApi#renderLods} + */ + public void renderDeferredLods(IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks) + { this.renderLodLayer(levelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, false); } + + private void renderLodLayer( + IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, + boolean renderingDeferredLayer) { if (ModInfo.IS_DEV_BUILD && !this.configOverrideReminderPrinted && MC.playerExists()) { + this.configOverrideReminderPrinted = true; + // remind the user that this is a development build MC.sendChatMessage(ModInfo.READABLE_NAME + " experimental build " + ModInfo.VERSION); MC.sendChatMessage("You are running an unsupported version of Distant Horizons!"); MC.sendChatMessage("Here be dragons!"); - this.configOverrideReminderPrinted = true; } + IProfilerWrapper profiler = MC.getProfiler(); profiler.pop(); // get out of "terrain" profiler.push("DH-RenderLevel"); + try { if (!RenderUtil.shouldLodsRender(levelWrapper)) @@ -472,29 +488,28 @@ public class ClientApi return; } - - //FIXME: Improve class hierarchy of DhWorld, IClientWorld, IServerWorld to fix all this hard casting - // (also in RenderUtil) IDhClientWorld dhClientWorld = SharedApi.getIDhClientWorld(); + if (dhClientWorld == null) + { + return; + } IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper); + DhApiRenderParam renderEventParam = + new DhApiRenderParam(mcProjectionMatrix, mcModelViewMatrix, + RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks), + RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), partialTicks); - try + if (renderingDeferredLayer) { if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEFAULT) { - DhApiRenderParam renderEventParam = - new DhApiRenderParam(mcProjectionMatrix, mcModelViewMatrix, - RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks), - RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), partialTicks); - - boolean renderingCanceled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, new DhApiBeforeRenderEvent.EventParam(renderEventParam)); - if (!this.rendererDisabledBecauseOfExceptions && !renderingCanceled) + this.renderingCancelledForThisFrame = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, new DhApiBeforeRenderEvent.EventParam(renderEventParam)); + if (!this.rendererDisabledBecauseOfExceptions && !this.renderingCancelledForThisFrame) { level.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); - ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, new DhApiAfterRenderEvent.EventParam(renderEventParam)); } } else if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEBUG) @@ -503,22 +518,25 @@ public class ClientApi ClientApi.testRenderer.render(); profiler.pop(); } - // the other rendererMode is DISABLED } - catch (RuntimeException e) + else { - this.rendererDisabledBecauseOfExceptions = true; - LOGGER.error("Renderer thrown an uncaught exception: ", e); - - MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons" - + " renderer has encountered an exception!"); - MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues."); - MC.sendChatMessage("\u00A74Exception detail: " + e); + if (!this.rendererDisabledBecauseOfExceptions && !this.renderingCancelledForThisFrame) + { + level.renderDeferred(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + + ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, new DhApiAfterRenderEvent.EventParam(renderEventParam)); + } } } catch (Exception e) { - LOGGER.error("client level rendering uncaught exception: ", e); + this.rendererDisabledBecauseOfExceptions = true; + LOGGER.error("Unexpected Renderer error in " + (renderingDeferredLayer ? "Opaque" : "Transparent") + " stage. Error: " + e.getMessage(), e); + + MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!"); + MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues."); + MC.sendChatMessage("\u00A74Exception detail: " + e); } finally { @@ -529,6 +547,7 @@ public class ClientApi + //=================// // DEBUG USE // //=================// 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 71200ea5f..ddd82bc8c 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 @@ -573,6 +573,7 @@ public class Config .setPerformance(EConfigEntryPerformance.NONE) .build(); + @Deprecated // TODO remove failed experiment public static ConfigEntry seamlessOverdraw = new ConfigEntry.Builder() .set(false) .comment("" diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java index 2fd6bcd7a..08ef20f1d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java @@ -274,27 +274,6 @@ public class ColumnRenderSource implements IDataSource // the source isn't empty, this object won't be empty after the method finishes this.isEmpty = false; - for (int i = 0; i < this.renderDataContainer.length; i += this.verticalDataCount) - { - int thisGenMode = RenderDataPointUtil.getGenerationMode(this.renderDataContainer[i]); - int srcGenMode = RenderDataPointUtil.getGenerationMode(renderSource.renderDataContainer[i]); - - if (srcGenMode == 0) - { - // the source hasn't been generated, don't write it - continue; - } - - // this object's column is older than the source's column, update it - if (thisGenMode <= srcGenMode) - { - ColumnArrayView thisColumnArrayView = new ColumnArrayView(this.renderDataContainer, this.verticalDataCount, i, this.verticalDataCount); - ColumnArrayView srcColumnArrayView = new ColumnArrayView(renderSource.renderDataContainer, renderSource.verticalDataCount, i, renderSource.verticalDataCount); - thisColumnArrayView.copyFrom(srcColumnArrayView); - - this.debugSourceFlags[i / this.verticalDataCount] = renderSource.debugSourceFlags[i / this.verticalDataCount]; - } - } localVersion.incrementAndGet(); } /** @@ -361,7 +340,7 @@ public class ColumnRenderSource implements IDataSource FullDataToRenderDataTransformer.convertColumnData(level, sourceBlockX + sourceDataPointBlockWidth * (blockOffsetX + x), sourceBlockZ + sourceDataPointBlockWidth * (blockOffsetZ + z), - columnArrayView, fullArrayView, 2); + columnArrayView, fullArrayView); dataChanged |= hash != columnArrayView.getDataHash(); } } @@ -391,7 +370,7 @@ public class ColumnRenderSource implements IDataSource FullDataToRenderDataTransformer.convertColumnData(level, sourceBlockX + sourceDataPointBlockWidth * relSourceX, sourceBlockZ + sourceDataPointBlockWidth * relSourceZ, - columnArrayView, fullArrayView, 2); + columnArrayView, fullArrayView); dataChanged |= hash != columnArrayView.getDataHash(); } } @@ -415,7 +394,7 @@ public class ColumnRenderSource implements IDataSource SingleColumnFullDataAccessor fullArrayView = chunkDataView.get(0, 0); FullDataToRenderDataTransformer.convertColumnData(level, dataCornerPos.x * sourceDataPointBlockWidth, dataCornerPos.z * sourceDataPointBlockWidth, - columnArrayView, fullArrayView, 2); + columnArrayView, fullArrayView); dataChanged = hash != columnArrayView.getDataHash(); this.fillDebugFlag(relStartX, relStartZ, 1, 1, ColumnRenderSource.DebugSourceFlag.DIRECT); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java index 3c82291cb..d9e83458f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java @@ -49,12 +49,9 @@ public final class BufferQuad /** This is both North/South and Up/Down since the merging logic is the same either way */ public short widthNorthSouthOrUpDown; - /** - * not final since it may need to be modified to be opaque - * - * @see LodQuadBuilder#fixTransparencyOverVoid - */ - public int color; + public final int color; + /** used by the Iris shader mod to determine how each LOD should be rendered */ + public final byte irisBlockMaterialId; public final byte skyLight; public final byte blockLight; @@ -66,7 +63,7 @@ public final class BufferQuad BufferQuad( short x, short y, short z, short widthEastWest, short widthNorthSouthOrUpDown, - int color, byte skylight, byte blockLight, + int color, byte irisBlockMaterialId, byte skylight, byte blockLight, EDhDirection direction) { if (widthEastWest == 0 || widthNorthSouthOrUpDown == 0) @@ -80,6 +77,7 @@ public final class BufferQuad this.widthEastWest = widthEastWest; this.widthNorthSouthOrUpDown = widthNorthSouthOrUpDown; this.color = color; + this.irisBlockMaterialId = irisBlockMaterialId; this.skyLight = skylight; this.blockLight = blockLight; this.direction = direction; @@ -301,6 +299,7 @@ public final class BufferQuad // do the quads' color, light, etc. match? if (this.color != quad.color || + this.irisBlockMaterialId != quad.irisBlockMaterialId || this.skyLight != quad.skyLight || this.blockLight != quad.blockLight) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java index 0584aa79b..d7535a524 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java @@ -36,7 +36,7 @@ public class ColumnBox LodQuadBuilder builder, short xSize, short ySize, short zSize, short x, short minY, short z, - int color, byte skyLight, byte blockLight, + int color, byte irisBlockMaterialId, byte skyLight, byte blockLight, long topData, long bottomData, ColumnArrayView[][] adjData) { short maxX = (short) (x + xSize); @@ -102,13 +102,13 @@ public class ColumnBox boolean skipTop = RenderDataPointUtil.doesDataPointExist(topData) && (RenderDataPointUtil.getYMin(topData) == maxY) && !isTopTransparent; if (!skipTop) { - builder.addQuadUp(x, maxY, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(EDhDirection.UP)), skyLightTop, blockLight); + builder.addQuadUp(x, maxY, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(EDhDirection.UP)), irisBlockMaterialId, skyLightTop, blockLight); } boolean skipBottom = RenderDataPointUtil.doesDataPointExist(bottomData) && (RenderDataPointUtil.getYMax(bottomData) == minY) && !isBottomTransparent; if (!skipBottom) { - builder.addQuadDown(x, minY, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(EDhDirection.DOWN)), skyLightBot, blockLight); + builder.addQuadDown(x, minY, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(EDhDirection.DOWN)), irisBlockMaterialId, skyLightBot, blockLight); } @@ -124,22 +124,22 @@ public class ColumnBox // add an adjacent face if this is opaque face or transparent over the void if (!isTransparent || overVoid) { - builder.addQuadAdj(EDhDirection.NORTH, x, minY, z, xSize, ySize, color, (byte) 15, blockLight); + builder.addQuadAdj(EDhDirection.NORTH, x, minY, z, xSize, ySize, color, irisBlockMaterialId, (byte) 15, blockLight); } } else if (adjDataNorth.length == 1) { makeAdjVerticalQuad(builder, adjDataNorth[0], EDhDirection.NORTH, x, minY, z, xSize, ySize, - color, adjOverlapNorth, skyLightTop, blockLight, + color, adjOverlapNorth, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } else { makeAdjVerticalQuad(builder, adjDataNorth[0], EDhDirection.NORTH, x, minY, z, (short) (xSize / 2), ySize, - color, adjOverlapNorth, skyLightTop, blockLight, + color, adjOverlapNorth, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); makeAdjVerticalQuad(builder, adjDataNorth[1], EDhDirection.NORTH, (short) (x + xSize / 2), minY, z, (short) (xSize / 2), ySize, - color, adjOverlapNorth, skyLightTop, blockLight, + color, adjOverlapNorth, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } } @@ -151,22 +151,22 @@ public class ColumnBox if (adjDataSouth == null) { if (!isTransparent || overVoid) - builder.addQuadAdj(EDhDirection.SOUTH, x, minY, maxZ, xSize, ySize, color, (byte) 15, blockLight); + builder.addQuadAdj(EDhDirection.SOUTH, x, minY, maxZ, xSize, ySize, color, irisBlockMaterialId, (byte) 15, blockLight); } else if (adjDataSouth.length == 1) { makeAdjVerticalQuad(builder, adjDataSouth[0], EDhDirection.SOUTH, x, minY, maxZ, xSize, ySize, - color, adjOverlapSouth, skyLightTop, blockLight, + color, adjOverlapSouth, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } else { makeAdjVerticalQuad(builder, adjDataSouth[0], EDhDirection.SOUTH, x, minY, maxZ, (short) (xSize / 2), ySize, - color, adjOverlapSouth, skyLightTop, blockLight, + color, adjOverlapSouth, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); makeAdjVerticalQuad(builder, adjDataSouth[1], EDhDirection.SOUTH, (short) (x + xSize / 2), minY, maxZ, (short) (xSize / 2), ySize, - color, adjOverlapSouth, skyLightTop, blockLight, + color, adjOverlapSouth, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } } @@ -178,21 +178,21 @@ public class ColumnBox if (adjDataWest == null) { if (!isTransparent || overVoid) - builder.addQuadAdj(EDhDirection.WEST, x, minY, z, zSize, ySize, color, (byte) 15, blockLight); + builder.addQuadAdj(EDhDirection.WEST, x, minY, z, zSize, ySize, color, irisBlockMaterialId, (byte) 15, blockLight); } else if (adjDataWest.length == 1) { makeAdjVerticalQuad(builder, adjDataWest[0], EDhDirection.WEST, x, minY, z, zSize, ySize, - color, adjOverlapWest, skyLightTop, blockLight, + color, adjOverlapWest, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } else { makeAdjVerticalQuad(builder, adjDataWest[0], EDhDirection.WEST, x, minY, z, (short) (zSize / 2), ySize, - color, adjOverlapWest, skyLightTop, blockLight, + color, adjOverlapWest, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); makeAdjVerticalQuad(builder, adjDataWest[1], EDhDirection.WEST, x, minY, (short) (z + zSize / 2), (short) (zSize / 2), ySize, - color, adjOverlapWest, skyLightTop, blockLight, + color, adjOverlapWest, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } } @@ -204,21 +204,21 @@ public class ColumnBox if (adjData[EDhDirection.EAST.ordinal() - 2] == null) { if (!isTransparent || overVoid) - builder.addQuadAdj(EDhDirection.EAST, maxX, minY, z, zSize, ySize, color, (byte) 15, blockLight); + builder.addQuadAdj(EDhDirection.EAST, maxX, minY, z, zSize, ySize, color, irisBlockMaterialId, (byte) 15, blockLight); } else if (adjDataEast.length == 1) { makeAdjVerticalQuad(builder, adjDataEast[0], EDhDirection.EAST, maxX, minY, z, zSize, ySize, - color, adjOverlapEast, skyLightTop, blockLight, + color, adjOverlapEast, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } else { makeAdjVerticalQuad(builder, adjDataEast[0], EDhDirection.EAST, maxX, minY, z, (short) (zSize / 2), ySize, - color, adjOverlapEast, skyLightTop, blockLight, + color, adjOverlapEast, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); makeAdjVerticalQuad(builder, adjDataEast[1], EDhDirection.EAST, maxX, minY, (short) (z + zSize / 2), (short) (zSize / 2), ySize, - color, adjOverlapEast, skyLightTop, blockLight, + color, adjOverlapEast, irisBlockMaterialId, skyLightTop, blockLight, topData, bottomData); } } @@ -228,7 +228,7 @@ public class ColumnBox private static void makeAdjVerticalQuad( LodQuadBuilder builder, ColumnArrayView adjColumnView, EDhDirection direction, short x, short yMin, short z, short horizontalWidth, short ySize, - int color, int debugOverlapColor, byte skyLightTop, byte blockLight, + int color, int debugOverlapColor, byte irisBlockMaterialId, byte skyLightTop, byte blockLight, long topData, long bottomData) { color = ColorUtil.applyShade(color, MC.getShade(direction)); @@ -236,7 +236,7 @@ public class ColumnBox if (adjColumnView == null || adjColumnView.size == 0 || RenderDataPointUtil.isVoid(adjColumnView.get(0))) { // there isn't any data adjacent to this LOD, add the vertical quad - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, color, (byte) 15, blockLight); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, color, irisBlockMaterialId, (byte) 15, blockLight); return; } @@ -362,7 +362,7 @@ public class ColumnBox if (firstFace) { - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, color, skyLight, blockLight); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, color, irisBlockMaterialId, skyLight, blockLight); } else { @@ -373,7 +373,7 @@ public class ColumnBox throw new RuntimeException("Loop error"); } - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (previousAdjDepth - yMin), color, skyLight, blockLight); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (previousAdjDepth - yMin), color, irisBlockMaterialId, skyLight, blockLight); previousAdjDepth = -1; } @@ -393,7 +393,7 @@ public class ColumnBox // The input face is completely inside the adj's face, don't render it if (debugOverlapColor != 0) { - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, debugOverlapColor, (byte) 15, (byte) 15); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, debugOverlapColor, irisBlockMaterialId, (byte) 15, (byte) 15); } } else @@ -402,14 +402,14 @@ public class ColumnBox if (adjYMax > yMin && debugOverlapColor != 0) { - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (adjYMax - yMin), debugOverlapColor, (byte) 15, (byte) 15); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (adjYMax - yMin), debugOverlapColor, irisBlockMaterialId, (byte) 15, (byte) 15); } // if this is the only face, use the yMax and break, // if there was another face finish the last one and then break if (firstFace) { - builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (yMax - adjYMax), color, + builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (yMax - adjYMax), color, irisBlockMaterialId, RenderDataPointUtil.getLightSky(adjPoint), blockLight); } else @@ -423,7 +423,7 @@ public class ColumnBox if (previousAdjDepth > adjYMax) { - builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, + builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, irisBlockMaterialId, RenderDataPointUtil.getLightSky(adjPoint), blockLight); } previousAdjDepth = -1; @@ -448,7 +448,7 @@ public class ColumnBox // the adj data intersects the higher part of the current data if (debugOverlapColor != 0) { - builder.addQuadAdj(direction, x, adjYMin, z, horizontalWidth, (short) (yMax - adjYMin), debugOverlapColor, (byte) 15, (byte) 15); + builder.addQuadAdj(direction, x, adjYMin, z, horizontalWidth, (short) (yMax - adjYMin), debugOverlapColor, irisBlockMaterialId, (byte) 15, (byte) 15); } // we start the creation of a new face @@ -459,12 +459,12 @@ public class ColumnBox // _______&&: y < depth ______ < yMax if (debugOverlapColor != 0) { - builder.addQuadAdj(direction, x, adjYMin, z, horizontalWidth, (short) (adjYMax - adjYMin), debugOverlapColor, (byte) 15, (byte) 15); + builder.addQuadAdj(direction, x, adjYMin, z, horizontalWidth, (short) (adjYMax - adjYMin), debugOverlapColor, irisBlockMaterialId, (byte) 15, (byte) 15); } if (firstFace) { - builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (yMax - adjYMax), color, + builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (yMax - adjYMax), color, irisBlockMaterialId, RenderDataPointUtil.getLightSky(adjPoint), blockLight); } else @@ -474,7 +474,7 @@ public class ColumnBox throw new RuntimeException("Loop error"); if (previousAdjDepth > adjYMax) { - builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, + builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, irisBlockMaterialId, RenderDataPointUtil.getLightSky(adjPoint), blockLight); } previousAdjDepth = -1; @@ -502,12 +502,12 @@ public class ColumnBox { // the input LOD is above all adjacent LODs and won't be affected // by them, add the vertical quad using the input's lighting and height - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, color, skyLightTop, blockLight); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, ySize, color, irisBlockMaterialId, skyLightTop, blockLight); } else if (previousAdjDepth != -1) { // We need to finish the last quad. - builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (previousAdjDepth - yMin), color, nextTopSkyLight, blockLight); + builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (previousAdjDepth - yMin), color, irisBlockMaterialId, nextTopSkyLight, blockLight); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java index 791f609b3..45c0f03dc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java @@ -85,17 +85,12 @@ public class CubicLodTemplate break; } case SHOW_DETAIL: + case SHOW_GENMODE: { color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel]; fullBright = true; break; } - case SHOW_GENMODE: - { - color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[RenderDataPointUtil.getGenerationMode(data)]; - fullBright = true; - break; - } case SHOW_OVERLAPPING_QUADS: { color = ColorUtil.WHITE; @@ -112,11 +107,14 @@ public class CubicLodTemplate throw new IllegalArgumentException("Unknown debug mode: " + debugging); } + byte blockMaterialId = RenderDataPointUtil.getBlockMaterialId(data); + ColumnBox.addBoxQuadsToBuilder( quadBuilder, // buffer width, ySize, width, // setWidth x, yMin, z, // setOffset color, // setColor + blockMaterialId, // irisBlockMaterialId RenderDataPointUtil.getLightSky(data), // setSkyLights fullBright ? 15 : RenderDataPointUtil.getLightBlock(data), // setBlockLights topData, bottomData, adjColumnViews); // setAdjData diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java index ae91cb56d..03ff71bf5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java @@ -135,7 +135,7 @@ public class LodQuadBuilder public void addQuadAdj( EDhDirection dir, short x, short y, short z, short widthEastWest, short widthNorthSouthOrUpDown, - int color, byte skyLight, byte blockLight) + int color, byte irisBlockMaterialId, byte skyLight, byte blockLight) { if (dir == EDhDirection.DOWN) { @@ -147,7 +147,7 @@ public class LodQuadBuilder return; } - BufferQuad quad = new BufferQuad(x, y, z, widthEastWest, widthNorthSouthOrUpDown, color, skyLight, blockLight, dir); + BufferQuad quad = new BufferQuad(x, y, z, widthEastWest, widthNorthSouthOrUpDown, color, irisBlockMaterialId, skyLight, blockLight, dir); ArrayList quadList = (this.doTransparency && ColorUtil.getAlpha(color) < 255) ? this.transparentQuads[dir.ordinal()] : this.opaqueQuads[dir.ordinal()]; if (!quadList.isEmpty() && ( @@ -163,7 +163,7 @@ public class LodQuadBuilder } // XZ - public void addQuadUp(short x, short maxY, short z, short widthEastWest, short widthNorthSouthOrUpDown, int color, byte skylight, byte blocklight) // TODO argument names are wrong + public void addQuadUp(short x, short maxY, short z, short widthEastWest, short widthNorthSouthOrUpDown, int color, byte irisBlockMaterialId, byte skylight, byte blocklight) // TODO argument names are wrong { // cave culling if (this.skipQuadsWithZeroSkylight && skylight == 0 && maxY < this.skyLightCullingBelow) @@ -171,7 +171,7 @@ public class LodQuadBuilder return; } - BufferQuad quad = new BufferQuad(x, maxY, z, widthEastWest, widthNorthSouthOrUpDown, color, skylight, blocklight, EDhDirection.UP); + BufferQuad quad = new BufferQuad(x, maxY, z, widthEastWest, widthNorthSouthOrUpDown, color, irisBlockMaterialId, skylight, blocklight, EDhDirection.UP); boolean isTransparent = (this.doTransparency && ColorUtil.getAlpha(color) < 255); ArrayList quadList = isTransparent ? this.transparentQuads[EDhDirection.UP.ordinal()] : this.opaqueQuads[EDhDirection.UP.ordinal()]; @@ -190,11 +190,11 @@ public class LodQuadBuilder quadList.add(quad); } - public void addQuadDown(short x, short y, short z, short width, short wz, int color, byte skylight, byte blocklight) + public void addQuadDown(short x, short y, short z, short width, short wz, int color, byte irisBlockMaterialId, byte skylight, byte blocklight) { if (skipQuadsWithZeroSkylight && skylight == 0 && y < skyLightCullingBelow) return; - BufferQuad quad = new BufferQuad(x, y, z, width, wz, color, skylight, blocklight, EDhDirection.DOWN); + BufferQuad quad = new BufferQuad(x, y, z, width, wz, color, irisBlockMaterialId, skylight, blocklight, EDhDirection.DOWN); ArrayList qs = (doTransparency && ColorUtil.getAlpha(color) < 255) ? transparentQuads[EDhDirection.DOWN.ordinal()] : opaqueQuads[EDhDirection.DOWN.ordinal()]; if (!qs.isEmpty() && @@ -219,6 +219,7 @@ public class LodQuadBuilder int[][] quadBase = DIRECTION_VERTEX_IBO_QUAD[quad.direction.ordinal()]; short widthEastWest = quad.widthEastWest; short widthNorthSouth = quad.widthNorthSouthOrUpDown; + byte normalIndex = (byte) quad.direction.ordinal(); EDhDirection.Axis axis = quad.direction.getAxis(); for (int i = 0; i < quadBase.length; i++) { @@ -255,13 +256,15 @@ public class LodQuadBuilder } putVertex(bb, (short) (quad.x + dx), (short) (quad.y + dy), (short) (quad.z + dz), quad.hasError ? ColorUtil.RED : quad.color, // TODO add debug config that allows toggling this + quad.hasError ? 0 : normalIndex, + quad.hasError ? 0 : quad.irisBlockMaterialId, quad.hasError ? 15 : quad.skyLight, quad.hasError ? 15 : quad.blockLight, mx, my, mz); } } - private void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte skylight, byte blocklight, int mx, int my, int mz) + private void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte normalIndex, byte irisBlockMaterialId, byte skylight, byte blocklight, int mx, int my, int mz) { skylight %= 16; blocklight %= 16; @@ -292,6 +295,11 @@ public class LodQuadBuilder bb.put(g); bb.put(b); bb.put(a); + + // Block ID and normal index are used by the Iris format + bb.put(irisBlockMaterialId); + bb.put(normalIndex); + bb.putShort((short) 0); // padding to make sure the vertex format as a whole is a multiple of 4 } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 8f077881b..9d376799b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -134,7 +134,7 @@ public class FullDataToRenderDataTransformer ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); SingleColumnFullDataAccessor fullArrayView = fullDataSource.get(x, z); - convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1); + convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView); if (fullArrayView.doesColumnExist()) { @@ -190,7 +190,7 @@ public class FullDataToRenderDataTransformer } ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); - convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1); + convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView); columnSource.fillDebugFlag(x, z, 1, 1, ColumnRenderSource.DebugSourceFlag.SPARSE); if (fullArrayView.doesColumnExist()) @@ -229,7 +229,7 @@ public class FullDataToRenderDataTransformer // TODO what does this mean? - private static void iterateAndConvert(IDhClientLevel level, int blockX, int blockZ, int genMode, ColumnArrayView column, SingleColumnFullDataAccessor data) + private static void iterateAndConvert(IDhClientLevel level, int blockX, int blockZ, ColumnArrayView column, SingleColumnFullDataAccessor data) { boolean avoidSolidBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EBlocksToAvoid.NON_COLLIDING); boolean colorBelowWithAvoidedBlocks = Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks.get(); @@ -308,7 +308,7 @@ public class FullDataToRenderDataTransformer // add the block isVoid = false; - long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, light, genMode); + long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, light, block.getIrisBlockMaterialId()); column.set(columnOffset, columnData); columnOffset++; } @@ -316,12 +316,12 @@ public class FullDataToRenderDataTransformer if (isVoid) { - column.set(0, RenderDataPointUtil.createVoidDataPoint((byte) genMode)); + column.set(0, RenderDataPointUtil.createVoidDataPoint()); } } // TODO what does this mean? - public static void convertColumnData(IDhClientLevel level, int blockX, int blockZ, ColumnArrayView columnArrayView, SingleColumnFullDataAccessor fullArrayView, int genMode) + public static void convertColumnData(IDhClientLevel level, int blockX, int blockZ, ColumnArrayView columnArrayView, SingleColumnFullDataAccessor fullArrayView) { if (!fullArrayView.doesColumnExist()) { @@ -337,12 +337,12 @@ public class FullDataToRenderDataTransformer if (dataTotalLength > columnArrayView.verticalSize()) { ColumnArrayView totalColumnData = new ColumnArrayView(new long[dataTotalLength], dataTotalLength, 0, dataTotalLength); - iterateAndConvert(level, blockX, blockZ, genMode, totalColumnData, fullArrayView); + iterateAndConvert(level, blockX, blockZ, totalColumnData, fullArrayView); columnArrayView.changeVerticalSizeFrom(totalColumnData); } else { - iterateAndConvert(level, blockX, blockZ, genMode, columnArrayView, fullArrayView); //Directly use the arrayView since it fits. + iterateAndConvert(level, blockX, blockZ, columnArrayView, fullArrayView); //Directly use the arrayView since it fits. } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index 8631ef63a..4bcd54335 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -41,7 +41,6 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.apache.logging.log4j.Logger; import java.io.Closeable; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; public class ClientLevelModule implements Closeable @@ -150,7 +149,18 @@ public class ClientLevelModule implements Closeable // either the renderer hasn't been started yet, or is being reloaded return; } - ClientRenderState.renderer.drawLODs(ClientRenderState.clientLevelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + ClientRenderState.renderer.drawLods(ClientRenderState.clientLevelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + } + + public void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + { + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState == null) + { + // either the renderer hasn't been started yet, or is being reloaded + return; + } + ClientRenderState.renderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } public void stopRenderer() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 504e7b1c1..45ec55f57 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -89,9 +89,11 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel @Override public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { - clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); - } + { this.clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } + + @Override + public void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + { this.clientside.renderDeferred(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index 0d5416104..bcf47d9cd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -82,9 +82,11 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS @Override public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { - clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); - } + { this.clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } + + @Override + public void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + { this.clientside.renderDeferred(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } @Override public void serverTick() { this.chunkToLodBuilder.tick(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java index 85c836d36..003053470 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java @@ -31,6 +31,7 @@ public interface IDhClientLevel extends IDhLevel void clientTick(); void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); + void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java index 4eb96e0b3..0bb40dc82 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java @@ -52,9 +52,8 @@ public abstract class AbstractRenderBuffer implements AutoCloseable - public static final int DEFAULT_MEMORY_ALLOCATION = (LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 3) * 8; - public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; - public static final int MAX_QUADS_PER_BUFFER = (1024 * 1024 * 1) / QUADS_BYTE_SIZE; + public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; // TODO what does the 4 represent + public static final int MAX_QUADS_PER_BUFFER = (1024 * 1024 * 1) / QUADS_BYTE_SIZE; // TODO what do these multiples represent? public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 9472798cc..629fffab0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -297,6 +297,9 @@ public class LodRenderSection implements IDebugRenderable } } + // probably used by Iris + public void disposeBufferForRecreate() { this.disposeActiveBuffer = true; } + /** * Try and swap in new render buffer for this section. Note that before this call, there should be no other 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 ee8c4a546..f355d4d4a 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 @@ -65,7 +65,12 @@ public class RenderBufferHandler implements AutoCloseable { this.lodQuadTree = lodQuadTree; - this.f3Message = new F3Screen.DynamicMessage(() -> LodUtil.formatLog("Rendered Buffer Count: " + this.loadedNearToFarBuffers.size())); + 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); + }); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index 66b63a02e..27b578e0d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -106,9 +106,12 @@ public class LodRenderProgram extends ShaderProgram else vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute vao.bind(); - // Now a pos+light. - vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true)); // 2+2+2+2 - vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 + + // TODO comment what each attribute represents + vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true)); // 2+2+2+2 // TODO probably color, blockpos + vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 // TODO ? + vao.setVertexAttribute(0, 2, VertexPointer.addUnsignedBytesPointer(4, true, true)); // +4 // TODO probably normal index and Iris block ID + try { vao.completeAndCheck(vertexByteCount); 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 e35e66b67..900ccf1cb 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,7 +47,6 @@ 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.apache.logging.log4j.Logger; import org.lwjgl.opengl.GL32; import java.awt.*; @@ -88,6 +87,10 @@ public class LodRenderer private int cachedWidth; private int cachedHeight; + // Iris sets this to enable a deferred rendering mode. + // DO NOT SET THIS TO FINAL!!! + private boolean deferTransparentRendering = false; + public void setupOffset(DhBlockPos pos) throws IllegalStateException @@ -214,15 +217,64 @@ public class LodRenderer - //===============// - // main renderer // - //===============// + //===========// + // rendering // + //===========// - public void drawLODs(IClientLevelWrapper clientLevelWrapper, Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + /** + * This will draw both opaque and transparent LODs if + * {@link LodRenderer#deferTransparentRendering} is disabled, + * otherwise it will only render opaque LODs. + */ + public void drawLods( + IClientLevelWrapper clientLevelWrapper, + Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, + float partialTicks, IProfilerWrapper profiler) + { + this.renderLodPass( + clientLevelWrapper, + baseModelViewMatrix, baseProjectionMatrix, + partialTicks, profiler, + false); + } + + /** + * This method is designed for Iris to be able + * to draw water in a deferred rendering context. + * It needs to be updated with any major changes, + * but shouldn't be activated as per deferWaterRendering. + */ + public void drawDeferredLods( + IClientLevelWrapper clientLevelWrapper, + Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, + float partialTicks, IProfilerWrapper profiler) { + this.renderLodPass( + clientLevelWrapper, + baseModelViewMatrix, baseProjectionMatrix, + partialTicks, profiler, + true); + } + + private void renderLodPass( + IClientLevelWrapper clientLevelWrapper, + Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, + float partialTicks, IProfilerWrapper profiler, + boolean runningDeferredPass) + { + //====================// + // validate rendering // + //====================// + + if (runningDeferredPass && !this.deferTransparentRendering) + { + return; + } + boolean renderingFirstPass = !runningDeferredPass; + if (this.rendererClosed) { - EVENT_LOGGER.error("drawLODs() called after close()!"); + EVENT_LOGGER.error("LOD rendering attempted after the renderer has been shut down!"); return; } @@ -238,19 +290,14 @@ public class LodRenderer return; } + + + //=================// + // rendering setup // + //=================// + try { - if (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass()) - { - // Do not do this while Iris compat is being worked on. - - // We do not have a wy to properly render shader shadow pass, since they can - // and often do change the projection entirely, as well as the output usage. - - //EVENT_LOGGER.debug("Skipping shadow pass render."); - return; - } - // Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one. ILightMapWrapper lightmap = MC_RENDER.getLightmapWrapper(clientLevelWrapper); if (lightmap == null) @@ -268,133 +315,12 @@ public class LodRenderer } drawSaveGLState.end("drawSaveGLState"); - - - //===================// - // draw params setup // - //===================// - - profiler.push("LOD draw setup"); - - if (!this.isSetupComplete) - { - this.setup(); - - // shouldn't normally happen, but just in case - if (!this.isSetupComplete) - { - return; - } - } - - if (MC_RENDER.getTargetFrameBufferViewportWidth() != this.cachedWidth || MC_RENDER.getTargetFrameBufferViewportHeight() != this.cachedHeight) - { - this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth(); - this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight(); - - // just resizing the textures doesn't work when Optifine is present, - // so recreate the textures with the new size instead - this.createColorAndDepthTextures(this.cachedWidth, this.cachedHeight); - } - - this.setActiveFramebufferId(this.framebuffer.getId()); - this.setActiveDepthTextureId(this.depthTexture.getTextureId()); - if (this.nullableColorTexture != null) - { - this.setActiveColorTextureId(this.nullableColorTexture.getTextureId()); - } - else - { - // get MC's color texture - int mcColorTextureId = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); - this.setActiveColorTextureId(mcColorTextureId); - } - // Bind LOD frame buffer - this.framebuffer.bind(); - - - if (this.usingMcFrameBuffer) - { - // recreating the GL State at this point is necessary in order to get the correct depth texture - minecraftGlState = new GLState(); - if (ENABLE_DUMP_GL_STATE) - { - tickLogger.debug("Re-saving GL state due to Optifine presence: " + minecraftGlState); // - } - - - // Due to using MC/Optifine's framebuffer we need to re-bind the depth texture, - // otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues - this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F); - - - // don't clear the color texture, that removes the sky - GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); - } - else - { - GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT); - } - - - GL32.glEnable(GL32.GL_DEPTH_TEST); - GL32.glDepthFunc(GL32.GL_LESS); - - // Set OpenGL polygon mode - boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get(); - if (renderWireframe) - { - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE); - //GL32.glDisable(GL32.GL_CULL_FACE); - } - else - { - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); - GL32.glEnable(GL32.GL_CULL_FACE); - } - - // Enable depth test and depth mask - GL32.glEnable(GL32.GL_DEPTH_TEST); - GL32.glDepthFunc(GL32.GL_LESS); - GL32.glDepthMask(true); - - // Disable blending - // We render opaque first, then transparent - GL32.glDisable(GL32.GL_BLEND); - - /*---------Bind required objects--------*/ - // Setup LodRenderProgram and the LightmapTexture if it has not yet been done - // also binds LightmapTexture, VAO, and ShaderProgram - if (!this.isSetupComplete) - { - this.setup(); - } - else - { - LodFogConfig newFogConfig = this.shaderProgram.isShaderUsable(); - if (newFogConfig != null) - { - this.shaderProgram.free(); - this.shaderProgram = new LodRenderProgram(newFogConfig); - - FogShader.INSTANCE.free(); - FogShader.INSTANCE = new FogShader(newFogConfig); - } - this.shaderProgram.bind(); - } - - /*---------Get required data--------*/ - //int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; - //Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks); - Mat4f projectionMatrix = RenderUtil.createLodProjectionMatrix(baseProjectionMatrix, partialTicks); Mat4f modelViewProjectionMatrix = new Mat4f(projectionMatrix); modelViewProjectionMatrix.multiply(RenderUtil.createLodModelViewMatrix(baseModelViewMatrix)); - /*---------Fill uniform data--------*/ - this.shaderProgram.fillUniformData(modelViewProjectionMatrix, /*Light map = GL_TEXTURE0*/ 0, - MC.getWrappedClientLevel().getMinHeight(), partialTicks); + this.setupGLStateAndRenderObjects(minecraftGlState, profiler, modelViewProjectionMatrix, partialTicks, renderingFirstPass); lightmap.bind(); if (ENABLE_IBO) @@ -402,7 +328,14 @@ public class LodRenderer this.quadIBO.bind(); } - this.bufferHandler.buildRenderListAndUpdateSections(this.getLookVector()); + if (renderingFirstPass) + { + this.bufferHandler.buildRenderListAndUpdateSections(this.getLookVector()); + + transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; + fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled; + } + @@ -412,72 +345,74 @@ public class LodRenderer LagSpikeCatcher drawLagSpikeCatcher = new LagSpikeCatcher(); - profiler.popPush("LOD Opaque"); - // TODO: Directional culling - this.bufferHandler.renderOpaque(this); - - if (Config.Client.Advanced.Graphics.Ssao.enabled.get()) + if (!runningDeferredPass) { - profiler.popPush("LOD SSAO"); - SSAORenderer.INSTANCE.render(minecraftGlState, projectionMatrix, partialTicks); - } - - profiler.popPush("LOD Fog"); - FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix); - FogShader.INSTANCE.render(partialTicks); - - //DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker - - // Render transparent LOD sections (such as water) - transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; - fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled; - - if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) - { - profiler.popPush("LOD Transparent"); + //===================================// + // standard (non-deferred) rendering // + //===================================// - GL32.glEnable(GL32.GL_BLEND); - GL32.glBlendEquation(GL32.GL_FUNC_ADD); - GL32.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); - this.bufferHandler.renderTransparent(this); - GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it... + + // Disable blending for opaque rendering + GL32.glDisable(GL32.GL_BLEND); + + profiler.popPush("LOD Opaque"); + // TODO: Directional culling + this.bufferHandler.renderOpaque(this); + + if (Config.Client.Advanced.Graphics.Ssao.enabled.get()) + { + profiler.popPush("LOD SSAO"); + SSAORenderer.INSTANCE.render(minecraftGlState, projectionMatrix, partialTicks); + } profiler.popPush("LOD Fog"); + FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix); FogShader.INSTANCE.render(partialTicks); + + //DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker + + if (!this.deferTransparentRendering) + { + this.renderTransparentBuffers(profiler, partialTicks); + } + + + if (this.usingMcFrameBuffer) + { + // If MC's framebuffer is being used the depth needs to be cleared to prevent rendering on top of MC. + // This should only happen when Optifine shaders are being used. + GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); + } + + drawLagSpikeCatcher.end("LodDraw"); + + + + //=============================// + // Apply to the MC FrameBuffer // + //=============================// + + profiler.popPush("LOD Apply"); + + GLState dhApplyGlState = new GLState(); + + // Copy the LOD framebuffer to Minecraft's framebuffer + DhApplyShader.INSTANCE.render(partialTicks); + + dhApplyGlState.restore(); + } - - if (Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) + else { - profiler.popPush("Debug wireframes"); - // Note: this can be very slow if a lot of boxes are being rendered - DebugRenderer.INSTANCE.render(modelViewProjectionMatrix); + //====================// + // deferred rendering // + //====================// + + this.renderTransparentBuffers(profiler, partialTicks); + + drawLagSpikeCatcher.end("LodTranslucentDraw"); } - if (this.usingMcFrameBuffer) - { - // If MC's framebuffer is being used the depth needs to be cleared to prevent rendering on top of MC. - // This should only happen when Optifine shaders are being used. - GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); - } - - drawLagSpikeCatcher.end("LodDraw"); - - - - //=============================// - // Apply to the MC FrameBuffer // - //=============================// - - profiler.popPush("LOD Apply"); - - GLState dhApplyGlState = new GLState(); - - // Copy the LOD framebuffer to Minecraft's framebuffer - DhApplyShader.INSTANCE.render(partialTicks); - - dhApplyGlState.restore(); - - //================// @@ -487,7 +422,13 @@ public class LodRenderer profiler.popPush("LOD cleanup"); LagSpikeCatcher drawCleanup = new LagSpikeCatcher(); - GLProxy.getInstance().runRenderThreadTasks(); + // GLProxy tasks should be run after all rendering has been done + boolean afterEnabledDeferredPass = this.deferTransparentRendering && !renderingFirstPass; + boolean afterOnlyRenderingPass = !this.deferTransparentRendering && renderingFirstPass; + if (afterEnabledDeferredPass || afterOnlyRenderingPass) + { + GLProxy.getInstance().runRenderThreadTasks(); + } lightmap.unbind(); if (ENABLE_IBO) @@ -497,6 +438,13 @@ public class LodRenderer this.shaderProgram.unbind(); + if (renderingFirstPass && Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) + { + profiler.popPush("Debug wireframes"); + // Note: this can be very slow if a lot of boxes are being rendered + DebugRenderer.INSTANCE.render(modelViewProjectionMatrix); + profiler.popPush("LOD cleanup"); + } minecraftGlState.restore(); drawCleanup.end("LodDrawCleanup"); @@ -512,15 +460,156 @@ public class LodRenderer } } - private static final Logger LOGGER = LogManager.getLogger(); + private void renderTransparentBuffers(IProfilerWrapper profiler, float partialTicks) + { + if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) + { + profiler.popPush("LOD Transparent"); + + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendEquation(GL32.GL_FUNC_ADD); + GL32.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); + this.bufferHandler.renderTransparent(this); + GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it... + + profiler.popPush("LOD Fog"); + FogShader.INSTANCE.render(partialTicks); + } + } + //=================// // Setup Functions // //=================// - /** Setup all render objects - REQUIRES to be in render thread */ - private void setup() + private void setupGLStateAndRenderObjects( + GLState minecraftGlState, IProfilerWrapper profiler, + Mat4f modelViewProjectionMatrix, + float partialTicks, + boolean firstPass) + { + //===================// + // draw params setup // + //===================// + + profiler.push("LOD draw setup"); + + if (!this.isSetupComplete) + { + this.setupRenderObjects(); + + // shouldn't normally happen, but just in case + if (!this.isSetupComplete) + { + return; + } + } + + if (MC_RENDER.getTargetFrameBufferViewportWidth() != this.cachedWidth || MC_RENDER.getTargetFrameBufferViewportHeight() != this.cachedHeight) + { + this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth(); + this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight(); + + // just resizing the textures doesn't work when Optifine is present, + // so recreate the textures with the new size instead + this.createColorAndDepthTextures(this.cachedWidth, this.cachedHeight); + } + + this.setActiveFramebufferId(this.framebuffer.getId()); + this.setActiveDepthTextureId(this.depthTexture.getTextureId()); + if (this.nullableColorTexture != null) + { + this.setActiveColorTextureId(this.nullableColorTexture.getTextureId()); + } + else + { + // get MC's color texture + int mcColorTextureId = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); + this.setActiveColorTextureId(mcColorTextureId); + } + // Bind LOD frame buffer + this.framebuffer.bind(); + + + if (this.usingMcFrameBuffer) + { + // recreating the GL State at this point is necessary in order to get the correct depth texture + minecraftGlState.saveState(); + if (ENABLE_DUMP_GL_STATE) + { + tickLogger.debug("Re-saving GL state due to Optifine presence: " + minecraftGlState); + } + + + // Due to using MC/Optifine's framebuffer we need to re-bind the depth texture, + // otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues + this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F); + + + // don't clear the color texture, that removes the sky + GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); + } + else if (firstPass) + { + GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT); + } + + + GL32.glEnable(GL32.GL_DEPTH_TEST); + GL32.glDepthFunc(GL32.GL_LESS); + + // Set OpenGL polygon mode + boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get(); + if (renderWireframe) + { + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE); + //GL32.glDisable(GL32.GL_CULL_FACE); + } + else + { + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); + GL32.glEnable(GL32.GL_CULL_FACE); + } + + // Enable depth test and depth mask + GL32.glEnable(GL32.GL_DEPTH_TEST); + GL32.glDepthFunc(GL32.GL_LESS); + GL32.glDepthMask(true); + + /*---------Bind required objects--------*/ + // Setup LodRenderProgram and the LightmapTexture if it has not yet been done + // also binds LightmapTexture, VAO, and ShaderProgram + if (!this.isSetupComplete) + { + this.setupRenderObjects(); + } + else + { + LodFogConfig newFogConfig = this.shaderProgram.isShaderUsable(); + if (newFogConfig != null) + { + this.shaderProgram.free(); + this.shaderProgram = new LodRenderProgram(newFogConfig); + + FogShader.INSTANCE.free(); + FogShader.INSTANCE = new FogShader(newFogConfig); + } + this.shaderProgram.bind(); + } + + /*---------Get required data--------*/ + //int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; + //Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks); + + + /*---------Fill uniform data--------*/ + this.shaderProgram.fillUniformData(modelViewProjectionMatrix, /*Light map = GL_TEXTURE0*/ 0, + MC.getWrappedClientLevel().getMinHeight(), partialTicks); + } + + /** Setup all render objects - MUST be called on the render thread */ + private void setupRenderObjects() { if (this.isSetupComplete) { @@ -647,12 +736,12 @@ public class LodRenderer - //======================// - // Cleanup Functions // - //======================// + //===================// + // Cleanup Functions // + //===================// /** - * cleanup and free all render objects. MUST be on the render thread + * cleanup and free all render objects. * (Many objects are Native, outside of JVM, and need manual cleanup) */ private void cleanup() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java index 54887840b..390ef01aa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java @@ -35,9 +35,11 @@ public class DefaultLodVertexFormats public static final LodVertexFormatElement ELEMENT_UV = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.FLOAT, 2, false); public static final LodVertexFormatElement ELEMENT_LIGHT_MAP_UV = new LodVertexFormatElement(1, LodVertexFormatElement.DataType.SHORT, 2, false); public static final LodVertexFormatElement ELEMENT_NORMAL = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 3, false); - public static final LodVertexFormatElement ELEMENT_PADDING = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 1, true); + public static final LodVertexFormatElement ELEMENT_BYTE_PADDING = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 1, true); public static final LodVertexFormatElement ELEMENT_LIGHT = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.UBYTE, 1, false); + public static final LodVertexFormatElement ELEMENT_IRIS_MATERIAL_INDEX = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 1, false); + public static final LodVertexFormatElement ELEMENT_IRIS_NORMAL_INDEX = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 1, false); public static final LodVertexFormat POSITION = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).build()); @@ -48,7 +50,21 @@ public class DefaultLodVertexFormats public static final LodVertexFormat POSITION_COLOR_TEX_LIGHTMAP = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).add(ELEMENT_LIGHT_MAP_UV).build()); public static final LodVertexFormat POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT = new LodVertexFormat(ImmutableList.builder() - .add(ELEMENT_POSITION).add(ELEMENT_PADDING).add(ELEMENT_LIGHT) - .add(ELEMENT_COLOR).build()); + .add(ELEMENT_POSITION) + .add(ELEMENT_BYTE_PADDING) + .add(ELEMENT_LIGHT) + .add(ELEMENT_COLOR) + .build()); + + public static final LodVertexFormat POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT_MATERIAL_ID_NORMAL_INDEX = new LodVertexFormat(ImmutableList.builder() + .add(ELEMENT_POSITION) + .add(ELEMENT_BYTE_PADDING) + .add(ELEMENT_LIGHT) + .add(ELEMENT_COLOR) + .add(ELEMENT_IRIS_MATERIAL_INDEX) + .add(ELEMENT_IRIS_NORMAL_INDEX) + .add(ELEMENT_BYTE_PADDING) + .add(ELEMENT_BYTE_PADDING) // padding is to make sure the format is a multiple of 4 + .build()); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java index bb0533fb3..edfdc8cf1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java @@ -138,8 +138,7 @@ public class LodUtil public static final int MAX_ALLOCATABLE_DIRECT_MEMORY = 64 * 1024 * 1024; /** the format of data stored in the GPU buffers */ - public static final LodVertexFormat LOD_VERTEX_FORMAT = DefaultLodVertexFormats.POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT; - + public static final LodVertexFormat LOD_VERTEX_FORMAT = DefaultLodVertexFormats.POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT_MATERIAL_ID_NORMAL_INDEX; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java index 800763083..344c58dd8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java @@ -202,7 +202,7 @@ public class RenderDataPointReducingList lowerMaxY, RenderDataPointUtil.getLightSky(higherData), RenderDataPointUtil.getLightBlock(higherData), - RenderDataPointUtil.getGenerationMode(higherData) + RenderDataPointUtil.getBlockMaterialId(higherData) ) ); @@ -829,7 +829,7 @@ public class RenderDataPointReducingList int size = view.size(); if (size <= 0) { - return RenderDataPointUtil.createVoidDataPoint((byte)(1)); + return RenderDataPointUtil.createVoidDataPoint(); } long highest; @@ -849,7 +849,7 @@ public class RenderDataPointReducingList } } //no visible segments, return void. - return RenderDataPointUtil.createVoidDataPoint((byte) (1)); + return RenderDataPointUtil.createVoidDataPoint(); } //second loop: merge the rest of the segments. @@ -887,7 +887,7 @@ public class RenderDataPointReducingList // so, if we didn't set any data points, add a void data point. if (writeIndex == 0) { - view.set(writeIndex++, RenderDataPointUtil.createVoidDataPoint((byte) (1))); + view.set(writeIndex++, RenderDataPointUtil.createVoidDataPoint()); } for (int size = view.size(); writeIndex < size; writeIndex++) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java index 77f6459c8..4d00bf0e7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java @@ -24,8 +24,6 @@ import com.seibel.distanthorizons.core.logging.SpamReducedLogger; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.IColumnDataView; -import java.util.Arrays; - /** * A helper class that is used to access the data from a long @@ -35,7 +33,7 @@ import java.util.Arrays; * * DataPoint Format:
* - * GM: generation mode
+ * BM: block material id
* A: color alpha
* R: color red
* G: color green
@@ -46,7 +44,7 @@ import java.util.Arrays; * SL: sky light
* * =======Bit layout=======
- * _ GM GM GM A A A A |
+ * BM BM BM BM A A A A |
* R R R R R R R R |
* G G G G G G G G |
* B B B B B B B B |

@@ -74,7 +72,7 @@ public class RenderDataPointUtil public final static int ALPHA_DOWNSIZE_SHIFT = 4; - public final static int GEN_TYPE_SHIFT = 60; + public final static int IRIS_BLOCK_MATERIAL_ID_SHIFT = 60; public final static int COLOR_SHIFT = 32; public final static int BLUE_SHIFT = COLOR_SHIFT; @@ -97,12 +95,11 @@ public class RenderDataPointUtil public final static long HEIGHT_DEPTH_MASK = 0xFFFFFF; public final static long BLOCK_LIGHT_MASK = 0xF; public final static long SKY_LIGHT_MASK = 0xF; - public final static long GEN_TYPE_MASK = 0b111; - public final static long COMPARE_SHIFT = GEN_TYPE_SHIFT; + public final static long IRIS_BLOCK_MATERIAL_ID_MASK = 0xF; + public final static long COMPARE_SHIFT = 0b111; public final static long HEIGHT_SHIFTED_MASK = HEIGHT_MASK << HEIGHT_SHIFT; public final static long DEPTH_SHIFTED_MASK = DEPTH_MASK << DEPTH_SHIFT; - public final static long GEN_TYPE_SHIFTED_MASK = GEN_TYPE_MASK << GEN_TYPE_SHIFT; public final static long VOID_SETTER = HEIGHT_SHIFTED_MASK | DEPTH_SHIFTED_MASK; @@ -112,27 +109,19 @@ public class RenderDataPointUtil // datapoint manipulation // //========================// - public static long createVoidDataPoint(byte generationMode) - { - if (generationMode == 0) - { - throw new IllegalArgumentException("Trying to create void datapoint with genMode 0, which is NOT allowed in DataPoint version 10!"); - } - - return (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; - } + public static long createVoidDataPoint() { return EMPTY_DATA; } - public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode) + public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int irisBlockMaterialId) { return createDataPoint( ColorUtil.getAlpha(color), ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color), - height, depth, lightSky, lightBlock, generationMode); + height, depth, lightSky, lightBlock, irisBlockMaterialId); } - public static long createDataPoint(int height, int depth, int color, int light, int generationMode) + public static long createDataPoint(int height, int depth, int color, int light, int irisBlockMaterialId) { LodUtil.assertTrue(light >= 0 && light < 256, "Raw Light value must be between 0 and 255!"); @@ -141,28 +130,29 @@ public class RenderDataPointUtil ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color), - height, depth, light % 16, light / 16, generationMode); + height, depth, + light % 16, light / 16, + irisBlockMaterialId); } - public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode) + public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int irisBlockMaterialId) { - LodUtil.assertTrue(generationMode != 0, "Trying to create datapoint with genMode 0, which is NOT allowed in DataPoint version 10!"); - LodUtil.assertTrue(height >= 0 && height < MAX_WORLD_Y_SIZE, "Trying to create datapoint with height[" + height + "] out of range!"); LodUtil.assertTrue(depth >= 0 && depth < MAX_WORLD_Y_SIZE, "Trying to create datapoint with depth[" + depth + "] out of range!"); LodUtil.assertTrue(lightSky >= 0 && lightSky < 16, "Trying to create datapoint with lightSky[" + lightSky + "] out of range!"); LodUtil.assertTrue(lightBlock >= 0 && lightBlock < 16, "Trying to create datapoint with lightBlock[" + lightBlock + "] out of range!"); + LodUtil.assertTrue(irisBlockMaterialId >= 0 && irisBlockMaterialId < 256, "Trying to create datapoint with irisBlockMaterialId[" + irisBlockMaterialId + "] out of range!"); + LodUtil.assertTrue(alpha >= 0 && alpha < 256, "Trying to create datapoint with alpha[" + alpha + "] out of range!"); LodUtil.assertTrue(red >= 0 && red < 256, "Trying to create datapoint with red[" + red + "] out of range!"); LodUtil.assertTrue(green >= 0 && green < 256, "Trying to create datapoint with green[" + green + "] out of range!"); LodUtil.assertTrue(blue >= 0 && blue < 256, "Trying to create datapoint with blue[" + blue + "] out of range!"); - LodUtil.assertTrue(generationMode >= 0 && generationMode < 8, "Trying to create datapoint with genMode[" + generationMode + "] out of range!"); LodUtil.assertTrue(depth <= height, "Trying to create datapoint with depth[" + depth + "] greater than height[" + height + "]!"); - return (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT + long out = (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT | (red & RED_MASK) << RED_SHIFT | (green & GREEN_MASK) << GREEN_SHIFT | (blue & BLUE_MASK) << BLUE_SHIFT @@ -170,8 +160,10 @@ public class RenderDataPointUtil | (depth & DEPTH_MASK) << DEPTH_SHIFT | (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT | (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT - | (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT + | (irisBlockMaterialId & IRIS_BLOCK_MATERIAL_ID_MASK) << IRIS_BLOCK_MATERIAL_ID_SHIFT ; + + return out; } public static long shiftHeightAndDepth(long dataPoint, short offset) @@ -195,19 +187,8 @@ public class RenderDataPointUtil public static byte getLightSky(long dataPoint) { return (byte) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); } public static byte getLightBlock(long dataPoint) { return (byte) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK); } - public static byte getGenerationMode(long dataPoint) - { - byte genMode = (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); - if (warnLogger.canMaybeLog() && doesDataPointExist(dataPoint) && genMode == 0) - { - warnLogger.warnInc("Existing datapoint with genMode 0 detected! This is invalid in DataPoint version 10!" - + " This may be caused by old data that has not been updated correctly."); - return 1; - } - return (genMode == 0) ? 1 : genMode; - } + public static byte getBlockMaterialId(long dataPoint) { return (byte) ((dataPoint >>> IRIS_BLOCK_MATERIAL_ID_SHIFT) & IRIS_BLOCK_MATERIAL_ID_MASK); } - public static long overrideGenerationMode(long current, byte b) { return (current & ~GEN_TYPE_SHIFTED_MASK) | ((b & GEN_TYPE_MASK) << GEN_TYPE_SHIFT); } public static boolean isVoid(long dataPoint) { return (((dataPoint >>> DEPTH_SHIFT) & HEIGHT_DEPTH_MASK) == 0); } @@ -244,7 +225,7 @@ public class RenderDataPointUtil getGreen(dataPoint) + " BL:" + getLightBlock(dataPoint) + " SL:" + getLightSky(dataPoint) + - " G:" + getGenerationMode(dataPoint); + " BID:" + getBlockMaterialId(dataPoint); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index b4b503095..a94880fbe 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -39,4 +39,6 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper int getLightEmission(); + byte getIrisBlockMaterialId(); + } From d106a79532e285b922dd98a532e48ec3df557aad Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jan 2024 19:46:14 -0600 Subject: [PATCH 02/34] Remove unnecessary warnings --- .../core/file/AbstractDataSourceHandler.java | 1 - .../core/render/glObject/buffer/GLBuffer.java | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java index 896283ef1..7aaa93a07 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java @@ -275,7 +275,6 @@ public abstract class AbstractDataSourceHandler Date: Sun, 21 Jan 2024 21:33:56 -0600 Subject: [PATCH 03/34] deprecate SHOW_GENMODE --- .../distanthorizons/api/enums/rendering/EDebugRendering.java | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java index 163c06267..b0e8ce7f0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java @@ -44,6 +44,7 @@ public enum EDebugRendering /** LOD colors are based on their detail */ SHOW_DETAIL, + @Deprecated /** LOD colors are based on their gen mode. */ SHOW_GENMODE, From 9c8d77a4f3a979bfa537c6fb633764509a09e0cc Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jan 2024 21:35:05 -0600 Subject: [PATCH 04/34] Add showBlockMaterial debug rendering and fix a couple block materials --- .../api/enums/rendering/EDebugRendering.java | 8 ++- .../distanthorizons/core/config/Config.java | 10 +-- .../bufferBuilding/CubicLodTemplate.java | 63 ++++++++++++++++++- .../distanthorizons/core/util/ColorUtil.java | 7 ++- .../block/IBlockStateWrapper.java | 35 ++++++++++- .../assets/distanthorizons/lang/en_us.json | 2 + 6 files changed, 114 insertions(+), 11 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java index b0e8ce7f0..62ee27786 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java @@ -48,6 +48,9 @@ public enum EDebugRendering /** LOD colors are based on their gen mode. */ SHOW_GENMODE, + /** Block Materials are often used by Iris shaders to determine how LODs should be rendered */ + SHOW_BLOCK_MATERIAL, + /** Only draw overlapping LOD quads. */ SHOW_OVERLAPPING_QUADS, @@ -62,8 +65,8 @@ public enum EDebugRendering case OFF: return SHOW_DETAIL; case SHOW_DETAIL: - return SHOW_GENMODE; - case SHOW_GENMODE: + return SHOW_BLOCK_MATERIAL; + case SHOW_BLOCK_MATERIAL: return SHOW_OVERLAPPING_QUADS; case SHOW_OVERLAPPING_QUADS: return SHOW_RENDER_SOURCE_FLAG; @@ -88,4 +91,5 @@ public enum EDebugRendering return OFF; } } + } 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 ddd82bc8c..e6d971141 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 @@ -1114,11 +1114,11 @@ public class Config .comment("" + "Should specialized colors/rendering modes be used? \n" + "\n" - + EDebugRendering.OFF + ": Fake chunks will be drawn with their normal colors. \n" - + EDebugRendering.SHOW_DETAIL + ": Fake chunks color will be based on their detail level. \n" - + EDebugRendering.SHOW_GENMODE + ": Fake chunks color will be based on their distant generation mode. \n" - + EDebugRendering.SHOW_OVERLAPPING_QUADS + ": Fake chunks will be drawn with total white, but overlapping quads will be drawn with red. \n" - + " but overlapping quads will be drawn with red, drawn as a wireframe.") + + EDebugRendering.OFF + ": LODs will be drawn with their normal colors. \n" + + EDebugRendering.SHOW_DETAIL + ": LODs' color will be based on their detail level. \n" + + EDebugRendering.SHOW_BLOCK_MATERIAL + ": LODs' color will be based on their material. \n" + + EDebugRendering.SHOW_OVERLAPPING_QUADS + ": LODs will be drawn with total white, but overlapping quads will be drawn with red. \n" + + "") .build(); public static ConfigEntry renderWireframe = new ConfigEntry.Builder() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java index 45c0f03dc..dbfebb5d5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java @@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil; import com.seibel.distanthorizons.api.enums.rendering.EDebugRendering; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView; +import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; /** @@ -60,6 +61,8 @@ public class CubicLodTemplate throw new IllegalArgumentException("Negative y size for the data! Data: " + RenderDataPointUtil.toString(data)); } + byte blockMaterialId = RenderDataPointUtil.getBlockMaterialId(data); + int color; @@ -91,6 +94,64 @@ public class CubicLodTemplate fullBright = true; break; } + case SHOW_BLOCK_MATERIAL: + { + switch (blockMaterialId) + { + case IBlockStateWrapper.IrisBlockMaterial.UNKOWN: + case IBlockStateWrapper.IrisBlockMaterial.AIR: // shouldn't normally be rendered, but just in case + color = ColorUtil.HOT_PINK; + break; + + case IBlockStateWrapper.IrisBlockMaterial.LEAVES: + color = ColorUtil.GREEN; + break; + case IBlockStateWrapper.IrisBlockMaterial.STONE: + color = ColorUtil.GRAY; + break; + case IBlockStateWrapper.IrisBlockMaterial.WOOD: + color = ColorUtil.BROWN; + break; + case IBlockStateWrapper.IrisBlockMaterial.METAL: + color = ColorUtil.DARK_GRAY; + break; + case IBlockStateWrapper.IrisBlockMaterial.DIRT: + color = ColorUtil.LIGHT_BROWN; + break; + case IBlockStateWrapper.IrisBlockMaterial.LAVA: + color = ColorUtil.ORANGE; + break; + case IBlockStateWrapper.IrisBlockMaterial.DEEPSLATE: + color = ColorUtil.BLACK; + break; + case IBlockStateWrapper.IrisBlockMaterial.SNOW: + color = ColorUtil.WHITE; + break; + case IBlockStateWrapper.IrisBlockMaterial.SAND: + color = ColorUtil.TAN; + break; + case IBlockStateWrapper.IrisBlockMaterial.TERRACOTTA: + color = ColorUtil.DARK_ORANGE; + break; + case IBlockStateWrapper.IrisBlockMaterial.NETHER_STONE: + color = ColorUtil.DARK_RED; + break; + case IBlockStateWrapper.IrisBlockMaterial.WATER: + color = ColorUtil.BLUE; + break; + case IBlockStateWrapper.IrisBlockMaterial.ILLUMINATED: + color = ColorUtil.YELLOW; + break; + + default: + // undefined color + color = ColorUtil.CYAN; + break; + } + + fullBright = true; + break; + } case SHOW_OVERLAPPING_QUADS: { color = ColorUtil.WHITE; @@ -107,8 +168,6 @@ public class CubicLodTemplate throw new IllegalArgumentException("Unknown debug mode: " + debugging); } - byte blockMaterialId = RenderDataPointUtil.getBlockMaterialId(data); - ColumnBox.addBoxQuadsToBuilder( quadBuilder, // buffer width, ySize, width, // setWidth diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java index f43e33c95..89ec90fa9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java @@ -39,17 +39,22 @@ public class ColorUtil public static final int BLACK = rgbToInt(0, 0, 0); public static final int WHITE = rgbToInt(255, 255, 255); public static final int RED = rgbToInt(255, 0, 0); + public static final int DARK_RED = rgbToInt(100, 0, 0); public static final int GREEN = rgbToInt(0, 255, 0); public static final int BLUE = rgbToInt(0, 0, 255); public static final int YELLOW = rgbToInt(255, 255, 0); public static final int CYAN = rgbToInt(0, 255, 255); public static final int MAGENTA = rgbToInt(255, 0, 255); public static final int ORANGE = rgbToInt(255, 128, 0); + public static final int DARK_ORANGE = rgbToInt(125, 62, 0); + public static final int TAN = rgbToInt(183, 165, 119); public static final int PINK = rgbToInt(255, 128, 128); + public static final int HOT_PINK = rgbToInt(255, 105, 180); public static final int GRAY = rgbToInt(128, 128, 128); public static final int LIGHT_GRAY = rgbToInt(192, 192, 192); public static final int DARK_GRAY = rgbToInt(64, 64, 64); - public static final int BROWN = rgbToInt(128, 64, 0); + public static final int BROWN = rgbToInt(68, 46, 24); + public static final int LIGHT_BROWN = rgbToInt(130, 112, 67); public static final int PURPLE = rgbToInt(128, 0, 128); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index a94880fbe..85bcd10cd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -24,11 +24,44 @@ import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; /** A Minecraft version independent way of handling Blocks. */ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper { + //===========// + // constants // + //===========// + int FULLY_TRANSPARENT = 0; - int FULLY_OPAQUE = 16; + int FULLY_OPAQUE = 16; + + /** contains the indices used by Iris to determine how different block types should be rendered */ + class IrisBlockMaterial + { + public static final byte UNKOWN = 0; + public static final byte LEAVES = 1; + public static final byte STONE = 2; + public static final byte WOOD = 3; + public static final byte METAL = 4; + public static final byte DIRT = 5; + public static final byte LAVA = 6; + public static final byte DEEPSLATE = 7; + public static final byte SNOW = 8; + public static final byte SAND = 9; + public static final byte TERRACOTTA = 10; + public static final byte NETHER_STONE = 11; + public static final byte WATER = 12; + // unlisted numbers are unused + + /** shouldn't normally be needed, but just in case */ + public static final byte AIR = 14; + public static final byte ILLUMINATED = 15; // Max value + } + + + //=========// + // methods // + //=========// + String getSerialString(); /** 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 7152b0b20..9b969e90d 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -785,6 +785,8 @@ "Show detail", "distanthorizons.config.enum.EDebugRendering.SHOW_GENMODE": "Show generation mode", + "distanthorizons.config.enum.EDebugRendering.SHOW_BLOCK_MATERIAL": + "Show Material", "distanthorizons.config.enum.EDebugRendering.SHOW_OVERLAPPING_QUADS": "Show overlapping quads", "distanthorizons.config.enum.EDebugRendering.SHOW_RENDER_SOURCE_FLAG": From d7eb8d9416a0d2fe4f7a332ea708e28ffc5fd299 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jan 2024 21:41:33 -0600 Subject: [PATCH 05/34] Add try-catches to F3Screen suppliers --- .../core/logging/f3/F3Screen.java | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java b/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java index e221f32ec..595628a15 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java @@ -20,6 +20,8 @@ package com.seibel.distanthorizons.core.logging.f3; import com.seibel.distanthorizons.coreapi.ModInfo; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.Closeable; import java.util.*; @@ -27,6 +29,8 @@ import java.util.function.Supplier; public class F3Screen { + private static final Logger LOGGER = LogManager.getLogger(); + private static final String[] DEFAULT_STRING = { "", // blank line for spacing ModInfo.READABLE_NAME + " version: " + ModInfo.VERSION @@ -98,10 +102,18 @@ public class F3Screen public void printTo(List list) { - String message = this.supplier.get(); - if (message != null) + + try { - list.add(message); + String message = this.supplier.get(); + if (message != null) + { + list.add(message); + } + } + catch (Exception e) + { + LOGGER.error("Unexpected Exception in F3 ["+DynamicMessage.class.getSimpleName()+"], error: "+e.getMessage(), e); } } @@ -118,10 +130,17 @@ public class F3Screen { for (Supplier supplier : this.supplierList) { - String message = supplier.get(); - if (message != null) + try { - list.add(message); + String message = supplier.get(); + if (message != null) + { + list.add(message); + } + } + catch (Exception e) + { + LOGGER.error("Unexpected Exception in F3 ["+DynamicMessage.class.getSimpleName()+"], error: "+e.getMessage(), e); } } } @@ -139,10 +158,17 @@ public class F3Screen public void printTo(List list) { - String[] message = this.supplier.get(); - if (message != null) + try { - list.addAll(Arrays.asList(message)); + String[] message = this.supplier.get(); + if (message != null) + { + list.addAll(Arrays.asList(message)); + } + } + catch (Exception e) + { + LOGGER.error("Unexpected Exception in F3 ["+DynamicMessage.class.getSimpleName()+"], error: "+e.getMessage(), e); } } From 4cb2bb97a8c88b6058fda075e4aa680fd83042f6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jan 2024 22:00:21 -0600 Subject: [PATCH 06/34] Fix wireframe rendering --- .../core/render/renderer/LodRenderer.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) 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 900ccf1cb..de8824a5e 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 @@ -387,6 +387,19 @@ public class LodRenderer drawLagSpikeCatcher.end("LodDraw"); + //=================// + // debug rendering // + //=================// + + if (Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) + { + profiler.popPush("Debug wireframes"); + // Note: this can be very slow if a lot of boxes are being rendered + DebugRenderer.INSTANCE.render(modelViewProjectionMatrix); + profiler.popPush("LOD cleanup"); + } + + //=============================// // Apply to the MC FrameBuffer // @@ -438,14 +451,6 @@ public class LodRenderer this.shaderProgram.unbind(); - if (renderingFirstPass && Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) - { - profiler.popPush("Debug wireframes"); - // Note: this can be very slow if a lot of boxes are being rendered - DebugRenderer.INSTANCE.render(modelViewProjectionMatrix); - profiler.popPush("LOD cleanup"); - } - minecraftGlState.restore(); drawCleanup.end("LodDrawCleanup"); From 7e287dab713126fad5516c3cf7403881aab155cb Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 17:46:30 -0500 Subject: [PATCH 07/34] 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; From 23b9f167471fc50ce8f9ce91314dde64954b4a93 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 18:34:17 -0500 Subject: [PATCH 08/34] aabb only --- .../core/pos/DhFrustumBounds.java | 26 ++++++++++++------- .../core/render/RenderBufferHandler.java | 7 +++-- .../core/render/renderer/LodRenderer.java | 17 +++++------- 3 files changed, 28 insertions(+), 22 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 70a2be8d4..6bac2c3bd 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 @@ -1,26 +1,33 @@ package com.seibel.distanthorizons.core.pos; -import org.joml.Math; import org.joml.Matrix4f; 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(Matrix4f matViewProjectionInv) + public DhFrustumBounds(Matrix4f matViewProjection, float minY, float maxY) { + Matrix4f matViewProjectionInv = new Matrix4f(matViewProjection); + matViewProjectionInv.invert(); + + //this.frustum = new FrustumIntersection(); + //this.frustum.set(matViewProjection); + matViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); + this.worldMinY = minY; + this.worldMaxY = maxY; } 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(); @@ -28,10 +35,11 @@ public class DhFrustumBounds 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; + 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 frustum.intersectAab(lodMin, lodMax) != FrustumIntersection.OUTSIDE; 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 cd19f38b6..928a31341 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 @@ -31,6 +31,7 @@ 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.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.Logger; @@ -87,7 +88,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(Matrix4f matViewProjectionInv, Vector3f lookForwardVector) + public void buildRenderListAndUpdateSections(IClientLevelWrapper clientLevelWrapper, Matrix4f matViewProjection, Vec3f lookForwardVector) { EDhDirection[] axisDirections = new EDhDirection[3]; @@ -192,7 +193,9 @@ 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); + float worldMinY = clientLevelWrapper.getMinHeight(); + float worldHeight = clientLevelWrapper.getHeight(); + DhFrustumBounds frustumBounds = new DhFrustumBounds(matViewProjection, worldMinY, worldMinY + worldHeight); // Update the sections boolean rebuildAllBuffers = this.rebuildAllBuffers.getAndSet(false); 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 df82adcf5..f4cbdbb50 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 @@ -48,7 +48,6 @@ 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.*; @@ -332,19 +331,15 @@ public class LodRenderer if (renderingFirstPass) { - final Vector3f WorldUp = new Vector3f(0f, 1f, 0f); + Vec3f viewDir = this.getLookVector(); + Vec3d viewPos = MC_RENDER.getCameraExactPosition(); - Vec3f _lookAt = this.getLookVector(); - Vector3f lookAt = new Vector3f(_lookAt.x, _lookAt.y, _lookAt.z); - Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); - - Matrix4f matViewProjectionInv = new Matrix4f() + Matrix4f matViewProjection = new Matrix4f() .setTransposed(projectionMatrix.getValuesAsArray()) - .lookAlong(lookAt, WorldUp) - .translate(-(float)cameraPos.x, -(float)cameraPos.y, -(float)cameraPos.z) - .invert(); + .lookAlong(viewDir.x, viewDir.y, viewDir.z, 0f, 1f, 0f) + .translate(-(float)viewPos.x, -(float)viewPos.y, -(float)viewPos.z); - this.bufferHandler.buildRenderListAndUpdateSections(matViewProjectionInv, lookAt); + this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matViewProjection, viewDir); transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled; From e771f8a53c88871901de627d5bc66986316842d8 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 19:14:02 -0500 Subject: [PATCH 09/34] fix frustum check --- .../core/pos/DhFrustumBounds.java | 24 +++++++++---------- .../core/render/RenderBufferHandler.java | 3 ++- .../core/render/renderer/LodRenderer.java | 4 +++- 3 files changed, 17 insertions(+), 14 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 6bac2c3bd..77f28dbd7 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 @@ -1,26 +1,27 @@ package com.seibel.distanthorizons.core.pos; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +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 FrustumIntersection frustum; private final Vector3f boundsMin = new Vector3f(); private final Vector3f boundsMax = new Vector3f(); private final float worldMinY; private final float worldMaxY; - public DhFrustumBounds(Matrix4f matViewProjection, float minY, float maxY) + public DhFrustumBounds(Matrix4fc matViewProjection, float minY, float maxY) { - Matrix4f matViewProjectionInv = new Matrix4f(matViewProjection); - matViewProjectionInv.invert(); - - //this.frustum = new FrustumIntersection(); - //this.frustum.set(matViewProjection); + this.frustum = new FrustumIntersection(); + this.frustum.set(matViewProjection); + Matrix4fc matViewProjectionInv = new Matrix4f(matViewProjection).invert(); matViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); this.worldMinY = minY; this.worldMaxY = maxY; @@ -35,11 +36,10 @@ public class DhFrustumBounds Vector3f lodMin = new Vector3f(lodPosX, worldMinY, lodPosZ); Vector3f lodMax = new Vector3f(lodPosX + lodSize, 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; + //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 frustum.intersectAab(lodMin, lodMax) != FrustumIntersection.OUTSIDE; - return true; + return 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 928a31341..796c641d6 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 @@ -36,6 +36,7 @@ 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.Matrix4fc; import org.joml.Vector3f; import java.util.Comparator; @@ -88,7 +89,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(IClientLevelWrapper clientLevelWrapper, Matrix4f matViewProjection, Vec3f lookForwardVector) + public void buildRenderListAndUpdateSections(IClientLevelWrapper clientLevelWrapper, Matrix4fc matViewProjection, Vec3f lookForwardVector) { EDhDirection[] axisDirections = new EDhDirection[3]; 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 f4cbdbb50..3455e3ba4 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 @@ -48,6 +48,7 @@ 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.*; @@ -334,7 +335,8 @@ public class LodRenderer Vec3f viewDir = this.getLookVector(); Vec3d viewPos = MC_RENDER.getCameraExactPosition(); - Matrix4f matViewProjection = new Matrix4f() + // TODO: find proper way to get view matrix, this breaks when perfectly up/down + Matrix4fc matViewProjection = new Matrix4f() .setTransposed(projectionMatrix.getValuesAsArray()) .lookAlong(viewDir.x, viewDir.y, viewDir.z, 0f, 1f, 0f) .translate(-(float)viewPos.x, -(float)viewPos.y, -(float)viewPos.z); From 08483d02c698259a4eab633dfe82ad2005070846 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 19:27:52 -0500 Subject: [PATCH 10/34] re-enable aabb --- .../seibel/distanthorizons/core/pos/DhFrustumBounds.java | 7 +++---- .../distanthorizons/core/render/renderer/LodRenderer.java | 4 +++- 2 files changed, 6 insertions(+), 5 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 77f28dbd7..6968551fb 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 @@ -1,6 +1,5 @@ package com.seibel.distanthorizons.core.pos; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Matrix4fc; @@ -36,9 +35,9 @@ public class DhFrustumBounds Vector3f lodMin = new Vector3f(lodPosX, worldMinY, lodPosZ); Vector3f lodMax = new Vector3f(lodPosX + lodSize, 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; + 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 frustum.testAab(lodMin, lodMax); } 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 3455e3ba4..143f74582 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 @@ -332,7 +332,7 @@ public class LodRenderer if (renderingFirstPass) { - Vec3f viewDir = this.getLookVector(); + Vec3f viewDir = MC_RENDER.getLookAtVector(); Vec3d viewPos = MC_RENDER.getCameraExactPosition(); // TODO: find proper way to get view matrix, this breaks when perfectly up/down @@ -340,6 +340,8 @@ public class LodRenderer .setTransposed(projectionMatrix.getValuesAsArray()) .lookAlong(viewDir.x, viewDir.y, viewDir.z, 0f, 1f, 0f) .translate(-(float)viewPos.x, -(float)viewPos.y, -(float)viewPos.z); + + // TODO: will also need a diff matrix for iris shadow pass! this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matViewProjection, viewDir); From 71536230b6f32b3574556910a382867fba9901b8 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 22:40:16 -0500 Subject: [PATCH 11/34] fix view matrix --- .../core/pos/DhFrustumBounds.java | 9 +++++---- .../core/render/RenderBufferHandler.java | 10 +++------- .../core/render/renderer/LodRenderer.java | 16 ++++++---------- .../minecraft/IMinecraftRenderWrapper.java | 3 +++ 4 files changed, 17 insertions(+), 21 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 6968551fb..d1b398abe 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 @@ -15,13 +15,14 @@ public class DhFrustumBounds private final float worldMaxY; - public DhFrustumBounds(Matrix4fc matViewProjection, float minY, float maxY) + public DhFrustumBounds(Matrix4fc matWorldViewProjection, float minY, float maxY) { this.frustum = new FrustumIntersection(); - this.frustum.set(matViewProjection); + this.frustum.set(matWorldViewProjection); + + Matrix4fc matWorldViewProjectionInv = new Matrix4f(matWorldViewProjection).invert(); + matWorldViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); - Matrix4fc matViewProjectionInv = new Matrix4f(matViewProjection).invert(); - matViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); this.worldMinY = minY; this.worldMaxY = maxY; } 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 796c641d6..ac2e9b207 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 @@ -19,7 +19,6 @@ package com.seibel.distanthorizons.core.render; -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; @@ -27,17 +26,14 @@ 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.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.Logger; -import org.joml.Matrix4f; import org.joml.Matrix4fc; -import org.joml.Vector3f; import java.util.Comparator; import java.util.Iterator; @@ -89,7 +85,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(IClientLevelWrapper clientLevelWrapper, Matrix4fc matViewProjection, Vec3f lookForwardVector) + public void buildRenderListAndUpdateSections(IClientLevelWrapper clientLevelWrapper, Matrix4fc matWorldViewProjection, Vec3f lookForwardVector) { EDhDirection[] axisDirections = new EDhDirection[3]; @@ -196,7 +192,7 @@ public class RenderBufferHandler implements AutoCloseable float worldMinY = clientLevelWrapper.getMinHeight(); float worldHeight = clientLevelWrapper.getHeight(); - DhFrustumBounds frustumBounds = new DhFrustumBounds(matViewProjection, worldMinY, worldMinY + worldHeight); + DhFrustumBounds frustumBounds = new DhFrustumBounds(matWorldViewProjection, worldMinY, worldMinY + worldHeight); // Update the sections boolean rebuildAllBuffers = this.rebuildAllBuffers.getAndSet(false); 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 143f74582..93a9570dd 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 @@ -332,18 +332,14 @@ public class LodRenderer if (renderingFirstPass) { - Vec3f viewDir = MC_RENDER.getLookAtVector(); - Vec3d viewPos = MC_RENDER.getCameraExactPosition(); - - // TODO: find proper way to get view matrix, this breaks when perfectly up/down - Matrix4fc matViewProjection = new Matrix4f() - .setTransposed(projectionMatrix.getValuesAsArray()) - .lookAlong(viewDir.x, viewDir.y, viewDir.z, 0f, 1f, 0f) - .translate(-(float)viewPos.x, -(float)viewPos.y, -(float)viewPos.z); - // TODO: will also need a diff matrix for iris shadow pass! - this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matViewProjection, viewDir); + Matrix4fc matWorldViewProjection = new Matrix4f() + .setTransposed(projectionMatrix.getValuesAsArray()) + .mul(MC_RENDER.getWorldViewMatrix()); + + Vec3f viewDir = this.getLookVector(); + this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matWorldViewProjection, viewDir); 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..4fcaf703d 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 @@ -36,6 +36,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; /** * Contains everything related to @@ -54,6 +55,8 @@ public interface IMinecraftRenderWrapper extends IBindable Vec3d getCameraExactPosition(); + Matrix4f getWorldViewMatrix(); + Mat4f getDefaultProjectionMatrix(float partialTicks); double getGamma(); From 5e924a00b164d161547ef65263d094d5413b16df Mon Sep 17 00:00:00 2001 From: NULL511 Date: Thu, 25 Jan 2024 23:18:43 -0500 Subject: [PATCH 12/34] final --- .../com/seibel/distanthorizons/core/pos/DhFrustumBounds.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 d1b398abe..f1960d483 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 @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.core.pos; +import org.jetbrains.annotations.NotNull; import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Matrix4fc; @@ -27,7 +28,8 @@ public class DhFrustumBounds this.worldMaxY = maxY; } - public boolean Intersects(DhLodPos lodBounds) + /** 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(); From d0822213d5379413452cbd0de79c47072725b2f9 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Fri, 26 Jan 2024 14:43:04 -0500 Subject: [PATCH 13/34] make frustum culling 1.19.4+ only --- .../distanthorizons/core/render/renderer/LodRenderer.java | 5 ++++- .../wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) 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 93a9570dd..60c6ba39e 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 @@ -334,9 +334,12 @@ public class LodRenderer { // TODO: will also need a diff matrix for iris shadow pass! + Matrix4f matWorldView = new Matrix4f() + .setTransposed(MC_RENDER.getWorldViewMatrix().getValuesAsArray()); + Matrix4fc matWorldViewProjection = new Matrix4f() .setTransposed(projectionMatrix.getValuesAsArray()) - .mul(MC_RENDER.getWorldViewMatrix()); + .mul(matWorldView); Vec3f viewDir = this.getLookVector(); this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matWorldViewProjection, viewDir); 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 4fcaf703d..f9cfd4036 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 @@ -55,7 +55,7 @@ public interface IMinecraftRenderWrapper extends IBindable Vec3d getCameraExactPosition(); - Matrix4f getWorldViewMatrix(); + Mat4f getWorldViewMatrix(); Mat4f getDefaultProjectionMatrix(float partialTicks); From 0e0f5ec3ea59fa979ed6d0313ed458578edaec6a Mon Sep 17 00:00:00 2001 From: NULL511 Date: Fri, 26 Jan 2024 16:17:51 -0500 Subject: [PATCH 14/34] cleanup --- .../wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java | 1 - 1 file changed, 1 deletion(-) 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 f9cfd4036..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 @@ -36,7 +36,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import org.jetbrains.annotations.Nullable; -import org.joml.Matrix4f; /** * Contains everything related to From 8a4172dda16c09b2b9d97c84611a21d500706b86 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 30 Jan 2024 19:28:32 -0600 Subject: [PATCH 15/34] Improve DhApi readme string --- .../main/java/com/seibel/distanthorizons/api/DhApi.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java index 45eac51f3..e0fc13fc4 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java @@ -58,7 +58,7 @@ public class DhApi * * Note: Don't use this string in your code. It may change and is only for reference. */ - public static String READ_ME = + public static final String READ_ME = "If you don't see Javadocs something is wrong. \n" + "If you are only using the full DH Mod in your build script, you won't have access to our javadocs and could potentially call into unsafe code. \n" + "\n" + @@ -69,6 +69,12 @@ public class DhApi "and suggested setup. \n" + // DH Dev note: no links were included to prevent link rot. ""; public static String readMe() { return READ_ME; } + + /** + * This is just a humorous way to reference the {@link DhApi#READ_ME} constant string and hopefully peak a few people's attention + * vs the relatively boring "readMe". + */ + public static final String HEY_YOU_YOURE_FINALLY_AWAKE = READ_ME; /** * This is just a humorous way to reference the {@link DhApi#READ_ME} constant string and hopefully peak a few people's attention * vs the relatively boring "readMe". From a27593149a098e7d482ee55001765c7928a7bee4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 30 Jan 2024 19:29:51 -0600 Subject: [PATCH 16/34] Fix AbstractShaderRenderer free() null pointer --- .../render/renderer/shaders/AbstractShaderRenderer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java index c9e97f36d..16d481b2f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java @@ -61,7 +61,13 @@ public abstract class AbstractShaderRenderer this.shader.unbind(); } - public void free() { this.shader.free(); } + public void free() + { + if (this.shader != null) + { + this.shader.free(); + } + } protected void onInit() {} From 4ab2fef1ac756f276e3d06965f50d59fc8b166a7 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 30 Jan 2024 19:33:04 -0600 Subject: [PATCH 17/34] reword a couple comments and minor reformatting --- .../events/IDhApiEventInjector.java | 2 +- .../DependencyInjection/OverrideInjector.java | 16 +++++++ .../OverridePriorityListContainer.java | 2 +- .../glObject/texture/DhFramebuffer.java | 43 ++++++++++--------- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java index 75f11f2b0..5bcd3eebc 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java @@ -51,7 +51,7 @@ public interface IDhApiEventInjector extends IDependencyInjector * @param eventParameterObject event parameter * @param the parameter type taken by the event handlers. * @param the {@link IDhApiEvent}'s class - * @return if any of bound event handlers returned that this event should be canceled. + * @return if any of the bound event handlers notified that this event should be canceled. */ > boolean fireAllEvents(Class abstractEvent, T eventParameterObject); diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java index e87368089..f858300e0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java @@ -48,6 +48,10 @@ public class OverrideInjector implements IOverrideInjector + //==============// + // constructors // + //==============// + public OverrideInjector() { String thisPackageName = this.getClass().getPackage().getName(); @@ -60,6 +64,10 @@ public class OverrideInjector implements IOverrideInjector + //=========// + // binding // + //=========// + @Override public void bind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation) throws IllegalStateException, IllegalArgumentException { @@ -103,6 +111,14 @@ public class OverrideInjector implements IOverrideInjector overrideContainer.addOverride(dependencyImplementation); } + + + + + //=========// + // getters // + //=========// + @Override @SuppressWarnings("unchecked") public T get(Class interfaceClass) throws ClassCastException diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java index 46084accb..4645c0ecf 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java @@ -42,7 +42,7 @@ public class OverridePriorityListContainer implements IBindable OverridePriorityPair priorityPair = new OverridePriorityPair(override, override.getPriority()); this.overridePairList.add(priorityPair); - sortList(); + this.sortList(); } /** @return true if the override was removed from the list, false otherwise. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java index 0cf428597..5104ee602 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java @@ -48,7 +48,7 @@ public class DhFramebuffer public void addDepthAttachment(int texture, EDhDepthBufferFormat depthBufferFormat) { - bind(); + this.bind(); if (depthBufferFormat.isCombinedStencil()) { @@ -61,19 +61,19 @@ public class DhFramebuffer this.hasDepthAttachment = true; } - + + @Override public void addColorAttachment(int index, int texture) { - int fb = id; - bind(); + this.bind(); GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0 + index, GL32.GL_TEXTURE_2D, texture, 0); - attachments.put(index, texture); + this.attachments.put(index, texture); } public void noDrawBuffers() { - bind(); + this.bind(); GL32.glDrawBuffers(new int[]{GL32.GL_NONE}); } @@ -81,59 +81,60 @@ public class DhFramebuffer { int[] glBuffers = new int[buffers.length]; int index = 0; - if (buffers.length > maxDrawBuffers) + if (buffers.length > this.maxDrawBuffers) { - throw new IllegalArgumentException("Cannot write to more than " + maxDrawBuffers + " draw buffers on this GPU"); + throw new IllegalArgumentException("Cannot write to more than " + this.maxDrawBuffers + " draw buffers on this GPU"); } for (int buffer : buffers) { - if (buffer >= maxColorAttachments) + if (buffer >= this.maxColorAttachments) { - throw new IllegalArgumentException("Only " + maxColorAttachments + " color attachments are supported on this GPU, but an attempt was made to write to a color attachment with index " + buffer); + throw new IllegalArgumentException("Only " + this.maxColorAttachments + " color attachments are supported on this GPU, but an attempt was made to write to a color attachment with index " + buffer); } glBuffers[index++] = GL32.GL_COLOR_ATTACHMENT0 + buffer; } - bind(); + this.bind(); GL32.glDrawBuffers(new int[]{GL32.GL_NONE}); } public void readBuffer(int buffer) { - bind(); + this.bind(); GL32.glReadBuffer(GL32.GL_COLOR_ATTACHMENT0 + buffer); } - public int getColorAttachment(int index) { return attachments.get(index); } + public int getColorAttachment(int index) { return this.attachments.get(index); } - public boolean hasDepthAttachment() { return hasDepthAttachment; } + public boolean hasDepthAttachment() { return this.hasDepthAttachment; } + @Override public void bind() { - if (id == -1) + if (this.id == -1) { throw new IllegalStateException("Framebuffer does not exist!"); } - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, id); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.id); } - public void bindAsReadBuffer() { GL32.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, id); } + public void bindAsReadBuffer() { GL32.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, this.id); } - public void bindAsDrawBuffer() { GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, id); } + public void bindAsDrawBuffer() { GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, this.id); } public void destroyInternal() { - GL32.glDeleteFramebuffers(id); + GL32.glDeleteFramebuffers(this.id); this.id = -1; } + @Override public int getStatus() { - bind(); + this.bind(); int status = GL32.glCheckFramebufferStatus(GL32.GL_FRAMEBUFFER); - return status; } From b622095883c13beafa05477b21f26a15c11979a4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 30 Jan 2024 19:43:37 -0600 Subject: [PATCH 18/34] Add and fix OverrideInjector unbinding --- .../DependencyInjection/OverrideInjector.java | 20 +++++++++++++------ .../OverridePriorityListContainer.java | 13 ++---------- .../IDependencyInjector.java | 2 +- .../IOverrideInjector.java | 12 ++++++----- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java index f858300e0..9fd6dd9d8 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java @@ -30,7 +30,7 @@ import java.util.HashMap; * This is done so other mods can override our methods to improve features down the line. * * @author James Seibel - * @version 2022-9-8 + * @version 2024-1-30 */ public class OverrideInjector implements IOverrideInjector { @@ -38,7 +38,6 @@ public class OverrideInjector implements IOverrideInjector private final HashMap, OverridePriorityListContainer> overrideContainerByInterface = new HashMap<>(); - /** * This is used to determine if an override is part of Distant Horizons' * Core or not. @@ -111,7 +110,15 @@ public class OverrideInjector implements IOverrideInjector overrideContainer.addOverride(dependencyImplementation); } - + @Override + public void unbind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation) + { + OverridePriorityListContainer overrideContainer = this.overrideContainerByInterface.get(dependencyInterface); + if (overrideContainer != null) + { + overrideContainer.removeOverride(dependencyImplementation); + } + } @@ -137,12 +144,13 @@ public class OverrideInjector implements IOverrideInjector + //==========// + // clearing // + //==========// + @Override public void clear() { this.overrideContainerByInterface.clear(); } - - - } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java index 4645c0ecf..143259ee8 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java @@ -48,17 +48,8 @@ public class OverridePriorityListContainer implements IBindable /** @return true if the override was removed from the list, false otherwise. */ public boolean removeOverride(IDhApiOverrideable override) { - if (this.overridePairList.contains(override)) - { - this.overridePairList.remove(override); - sortList(); - - return true; - } - else - { - return false; - } + boolean overrideRemoved = this.overridePairList.removeIf((pair) -> pair.override.equals(override)); + return overrideRemoved; } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java index 3855a6557..9bb3b4e12 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java @@ -83,7 +83,7 @@ public interface IDependencyInjector /** Removes all bound dependencies. */ - public void clear(); + void clear(); diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java index b37883b59..982dda17b 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java @@ -28,21 +28,22 @@ public interface IOverrideInjector * All core overrides should have this priority.
* Should be lower than {@link IOverrideInjector#MIN_NON_CORE_OVERRIDE_PRIORITY}. */ - public static final int CORE_PRIORITY = -1; + int CORE_PRIORITY = -1; /** * The lowest priority non-core overrides can have. * Should be higher than {@link IOverrideInjector#CORE_PRIORITY}. */ - public static final int MIN_NON_CORE_OVERRIDE_PRIORITY = 0; + int MIN_NON_CORE_OVERRIDE_PRIORITY = 0; /** The priority given to overrides that don't explicitly define a priority. */ - public static final int DEFAULT_NON_CORE_OVERRIDE_PRIORITY = 10; + int DEFAULT_NON_CORE_OVERRIDE_PRIORITY = 10; /** * See {@link IDependencyInjector#bind(Class, IBindable) bind(Class, IBindable)} for full documentation. * - * @throws IllegalArgumentException if a non-Distant Horizons Override with the priority CORE is passed in or a invalid priority value. + * @throws IllegalArgumentException if a non-Distant Horizons Override with the priority {@link IOverrideInjector#CORE_PRIORITY} is passed in + * or an override is passed in with an invalid priority value. * @throws IllegalStateException if another override with the given priority already has been bound. * @see IDependencyInjector#bind(Class, IBindable) */ @@ -66,7 +67,8 @@ public interface IOverrideInjector */ T get(Class interfaceClass, int priority) throws ClassCastException; - + /** Removes the given concrete {@link IDhApiOverrideable} bound to the given interface. */ + void unbind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation); /** Removes all bound overrides. */ void clear(); From ab88d06cff036e32743aab78afb1181ed4ffe17a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 30 Jan 2024 19:50:23 -0600 Subject: [PATCH 19/34] Remove fog config from LodRenderProgram --- .../render/renderer/LodRenderProgram.java | 30 +++++++------------ .../core/render/renderer/LodRenderer.java | 6 ++-- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index 27b578e0d..70597edeb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -40,7 +40,6 @@ public class LodRenderProgram extends ShaderProgram public static final String VERTEX_SHADER_PATH = "shaders/standard.vert"; public static final String VERTEX_CURVE_SHADER_PATH = "shaders/curve.vert"; public static final String FRAGMENT_SHADER_PATH = "shaders/flat_shaded.frag"; - private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class); public final AbstractVertexAttribute vao; @@ -67,16 +66,15 @@ public class LodRenderProgram extends ShaderProgram // Debug Uniform public final int whiteWorldUniform; - private final LodFogConfig fogConfig; + // This will bind AbstractVertexAttribute - public LodRenderProgram(LodFogConfig fogConfig) + public LodRenderProgram() { - super(() -> Shader.loadFile(fogConfig.earthCurveRatio != 0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH, + super(() -> Shader.loadFile(Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get() != 0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH, false, new StringBuilder()).toString(), () -> Shader.loadFile(FRAGMENT_SHADER_PATH, false, new StringBuilder()).toString(), "fragColor", new String[]{"vPosition", "color"}); - this.fogConfig = fogConfig; combinedMatUniform = getUniformLocation("combinedMatrix"); modelOffsetUniform = getUniformLocation("modelOffset"); @@ -123,25 +121,17 @@ public class LodRenderProgram extends ShaderProgram } if (earthRadiusUniform != -1) setUniform(earthRadiusUniform, - /*6371KM*/ 6371000.0f / fogConfig.earthCurveRatio); + /*6371KM*/ 6371000.0f / Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get()); + // Noise Uniforms - setUniform(noiseEnabledUniform, fogConfig.noiseEnable); - setUniform(noiseStepsUniform, fogConfig.noiseSteps); - setUniform(noiseIntensityUniform, fogConfig.noiseIntensity); - setUniform(noiseDropoffUniform, fogConfig.noiseDropoff); + setUniform(noiseEnabledUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseEnabled.get()); + setUniform(noiseStepsUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseSteps.get()); + setUniform(noiseIntensityUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseIntensity.get().floatValue()); + setUniform(noiseDropoffUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseDropoff.get()); } - // If not usable, return a new LodFogConfig to be constructed - public LodFogConfig isShaderUsable() // TODO replace with a config listener, look at LodFogConfig for more info - { - LodFogConfig newConfig = LodFogConfig.generateFogConfig(); - if (fogConfig.equals(newConfig)) - { - return null; - } - return newConfig; - } + // Override ShaderProgram.bind() public void bind() 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..6ebacb699 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 @@ -594,8 +594,8 @@ public class LodRenderer LodFogConfig newFogConfig = this.shaderProgram.isShaderUsable(); if (newFogConfig != null) { - this.shaderProgram.free(); - this.shaderProgram = new LodRenderProgram(newFogConfig); + this.lodRenderProgram.free(); + this.lodRenderProgram = new LodRenderProgram(); FogShader.INSTANCE.free(); FogShader.INSTANCE = new FogShader(newFogConfig); @@ -635,7 +635,7 @@ public class LodRenderer EVENT_LOGGER.info("Setting up renderer"); this.isSetupComplete = true; - this.shaderProgram = new LodRenderProgram(LodFogConfig.generateFogConfig()); // TODO this doesn't actually use the fog config + this.lodRenderProgram = new LodRenderProgram(); if (ENABLE_IBO) { this.quadIBO = new QuadElementBuffer(); From 15ee6a9512ba5850b606fcd46651cfa2144b9999 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 31 Jan 2024 21:48:50 -0600 Subject: [PATCH 20/34] Add render events for Iris --- .../api/enums/rendering/EDhApiRenderPass.java | 17 + .../override/rendering/IDhApiFramebuffer.java | 59 ++++ .../rendering/IDhApiShaderProgram.java | 65 ++++ .../interfaces/render/IDhApiRenderProxy.java | 43 ++- .../abstractEvents/DhApiAfterRenderEvent.java | 22 +- .../DhApiBeforeApplyShaderRenderEvent.java | 49 +++ .../DhApiBeforeBufferRenderEvent.java | 71 +++++ .../DhApiBeforeDeferredRenderEvent.java | 37 +++ .../DhApiBeforeRenderCleanupEvent.java | 47 +++ .../DhApiBeforeRenderEvent.java | 20 +- .../DhApiBeforeRenderPassEvent.java | 54 ++++ .../DhApiBeforeRenderSetupEvent.java | 50 +++ .../DhApiBeforeTextureClearEvent.java | 49 +++ .../DhApiScreenResizeEvent.java | 77 +++++ .../DhApiRenderParam.java | 58 +++- .../core/api/internal/ClientApi.java | 89 ++++-- .../bufferBuilding/ColumnRenderBuffer.java | 9 +- .../core/level/ClientLevelModule.java | 9 +- .../core/level/DhClientLevel.java | 9 +- .../core/level/DhClientServerLevel.java | 9 +- .../core/level/IDhClientLevel.java | 5 +- .../core/render/AbstractRenderBuffer.java | 5 +- .../core/render/DhApiRenderProxy.java | 35 +- .../core/render/RenderBufferHandler.java | 10 +- .../glObject/texture/DhFramebuffer.java | 42 +-- .../render/renderer/LodRenderProgram.java | 59 ++-- .../core/render/renderer/LodRenderer.java | 301 +++++++++++------- 27 files changed, 1021 insertions(+), 279 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiRenderPass.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiFramebuffer.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeApplyShaderRenderEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeDeferredRenderEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderPassEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderSetupEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeTextureClearEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiScreenResizeEvent.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiRenderPass.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiRenderPass.java new file mode 100644 index 000000000..260609f8d --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiRenderPass.java @@ -0,0 +1,17 @@ +package com.seibel.distanthorizons.api.enums.rendering; + +/** + * OPAQUE_AND_TRANSPARENT,
+ * OPAQUE,
+ * TRANSPARENT,
+ * + * @author James Seibel + * @version 2024-1-30 + * @since API 1.1.0 + */ +public enum EDhApiRenderPass +{ + OPAQUE_AND_TRANSPARENT, + OPAQUE, + TRANSPARENT, +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiFramebuffer.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiFramebuffer.java new file mode 100644 index 000000000..67c702b2f --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiFramebuffer.java @@ -0,0 +1,59 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.interfaces.override.rendering; + +import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; + +/** + * @author James Seibel + * @version 2024-1-24 + * @since API 1.1.0 + */ +public interface IDhApiFramebuffer extends IDhApiOverrideable +{ + + /** + * If this method is called that means this program has the highest priority as defined by {@link IDhApiOverrideable#getPriority()} + * and gets to decide if it wants to be used to render this frame or not.

+ * + * If this method returns true then this program will be used for this frame.
+ * If this returns false then the default DH {@link IDhApiShaderProgram} will be used instead. + */ + boolean overrideThisFrame(); + + /** Runs any necessary binding this program needs so rendering can be done. */ + void bind(); + + /** Binds the given OpenGL depth texture ID. */ + void addDepthAttachment(int textureId, boolean isCombinedStencil); + + /** @return the OpenGL ID for this shader program */ + int getId(); + + /** @return the OpenGL framebuffer status as defined by glCheckFramebufferStatus */ + int getStatus(); + + /** Binds the given OpenGL texture ID to the given texture index relative to OpenGL's GL_COLOR_ATTACHMENT0 */ + void addColorAttachment(int textureIndex, int textureId); + + /** Destroys this framebuffer's OpenGL object(s). */ + void destroy(); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java new file mode 100644 index 000000000..2c02f6c63 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java @@ -0,0 +1,65 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.interfaces.override.rendering; + +import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.coreapi.util.math.Vec3f; + +/** + * @author James Seibel + * @version 2024-1-24 + * @since API 1.1.0 + */ +public interface IDhApiShaderProgram extends IDhApiOverrideable +{ + + /** + * If this method is called that means this program has the highest priority as defined by {@link IDhApiOverrideable#getPriority()} + * and gets to decide if it wants to be used to render this frame or not.

+ * + * If this method returns true then this program will be used for this frame.
+ * If this returns false then the default DH {@link IDhApiShaderProgram} will be used instead. + */ + boolean overrideThisFrame(); + + /** @return the OpenGL ID for this shader program */ + int getId(); + + /** Free any OpenGL objects owned by this program. */ + void free(); + + /** Runs any necessary binding this program needs so rendering can be done. */ + void bind(); + /** Runs any necessary unbinding this program needs so rendering can be done by another program. */ + void unbind(); + + + /** sets up the necessary uniforms for rendering */ + void fillUniformData(DhApiRenderParam renderParameters); + + /** sets the vec3 that all DH verticies should be offset by when rendering */ + void setModelOffsetPos(Vec3f modelPos); + + /** Binds the given Vertex Buffer Object to this shader program for rendering. */ + void bindVertexBuffer(int vbo); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java index 985dd4be9..3401835d9 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.render; import com.seibel.distanthorizons.api.objects.DhApiResult; + /** * Used to interact with Distant Horizons' rendering system. * @@ -45,34 +46,42 @@ public interface IDhApiRenderProxy */ DhApiResult clearRenderDataCache(); - /** - * Returns the name of Distant Horizons' FrameBuffer.
- * Will return {@link DhApiResult#success} = false and {@link DhApiResult#payload} = -1 if the FrameBuffer hasn't been created yet. - */ - DhApiResult getDhFrameBufferId(); - /** - * Sets the FrameBuffer name that Distant Horizons will draw to after it finishes generating a frame texture.
- * Setting this to -1 will cause Distant Horizons to use Minecraft's FrameBuffer.

- * - * Will return {@link DhApiResult#success} = false given name isn't a valid FrameBuffer. - */ - DhApiResult setTargetFrameBufferId(int frameBufferId); - /** - * Returns the FrameBuffer name that Distant Horizons will draw to after it finishes generating a frame texture.
- * By default this will be Minecraft's FrameBuffer. - */ - DhApiResult getTargetFrameBufferId(); + + //=======================// + // OpenGL object getters // + //=======================// /** * Returns the name of Distant Horizons' depth texture.
* Will return {@link DhApiResult#success} = false and {@link DhApiResult#payload} = -1 if the texture hasn't been created yet. */ DhApiResult getDhDepthTextureId(); + /** * Returns the name of Distant Horizons' color texture.
* Will return {@link DhApiResult#success} = false and {@link DhApiResult#payload} = -1 if the texture hasn't been created yet. */ DhApiResult getDhColorTextureId(); + + + //======================// + // Shader compatibility // + //======================// + + /** + * If set to true DH won't render opaque and transparent LODs in the same pass. + * Instead, opaque objects will be rendered at the normal time, but + * transparent objects will only be rendered in a second pass during Minecraft's + * own transparent rendering pass. + */ + void setDeferTransparentRendering(boolean deferTransparentRendering); + /** @return If DH should defer transparent rendering or not. */ + boolean getDeferTransparentRendering(); + + /** This may change based on FOV, player speed, and other factors. */ + float getNearClipPlaneDistanceInBlocks(float partialTicks); + + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java index af5e84323..05da17b96 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java @@ -29,14 +29,14 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp * did to the OpenGL state, so the state should be back to Minecraft's defaults. * * @author James Seibel - * @version 2023-6-23 + * @version 2024-1-31 * @see DhApiRenderParam * @since API 1.0.0 */ -public abstract class DhApiAfterRenderEvent implements IDhApiEvent +public abstract class DhApiAfterRenderEvent implements IDhApiEvent { /** Fired after Distant Horizons finishes rendering fake chunks. */ - public abstract void afterRender(DhApiEventParam input); + public abstract void afterRender(DhApiEventParam event); //=========================// @@ -44,20 +44,6 @@ public abstract class DhApiAfterRenderEvent implements IDhApiEvent input) { this.afterRender(input); } - - - //==================// - // parameter object // - //==================// - - public static class EventParam extends DhApiRenderParam - { - public EventParam(DhApiRenderParam parent) - { - super(parent.mcProjectionMatrix, parent.mcModelViewMatrix, parent.dhProjectionMatrix, parent.dhModelViewMatrix, parent.partialTicks); - } - - } + public final void fireEvent(DhApiEventParam event) { this.afterRender(event); } } \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeApplyShaderRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeApplyShaderRenderEvent.java new file mode 100644 index 000000000..60281a1ac --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeApplyShaderRenderEvent.java @@ -0,0 +1,49 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Fired before DH runs its apply shader. + * The apply shader is a shader that copies over everything DH has rendered + * for this pass into MC's framebuffers so it can be rendered to the screen. + * Canceling this event prevents the apply shader from running. + * + * @author James Seibel + * @version 2024-1-31 + * @since API 1.1.0 + */ +public abstract class DhApiBeforeApplyShaderRenderEvent implements IDhApiCancelableEvent +{ + /** Fired before the apply shader is run. */ + public abstract void beforeRender(DhApiCancelableEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiCancelableEventParam event) { this.beforeRender(event); } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java new file mode 100644 index 000000000..1bbb88b2b --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java @@ -0,0 +1,71 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.coreapi.util.math.Vec3f; + +/** + * Called before Distant Horizons starts rendering a buffer.
+ * This event cannot be cancelled, use {@link DhApiBeforeRenderEvent} if you want to cancel rendering. + * + * @author James Seibel + * @version 2023-1-31 + * @since API 1.1.0 + * + * @see DhApiBeforeRenderEvent + */ +public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent +{ + /** Fired immediately before Distant Horizons starts rendering a buffer. */ + public abstract void beforeRender(DhApiEventParam input); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam input) { this.beforeRender(input); } + + + //==================// + // parameter object // + //==================// + + public static class EventParam extends DhApiRenderParam + { + /** + * Measured in blocks. + * Should be applied to the model view matrix to move the buffer into its proper place. + */ + public final Vec3f modelPos; + + + public EventParam(DhApiRenderParam parent, Vec3f modelPos) + { + super(parent); + this.modelPos = modelPos; + } + } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeDeferredRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeDeferredRenderEvent.java new file mode 100644 index 000000000..3f22c4a54 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeDeferredRenderEvent.java @@ -0,0 +1,37 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; + +/** + * Called before Distant Horizons starts rendering the deferred rendering pass.
+ * Will only happen if {@link IDhApiRenderProxy#getDeferTransparentRendering()} is true.
+ * Generally this is only used when shaders are enabled.
+ * Canceling the event will prevent DH from rendering the deferred pass that frame. + * + * @author James Seibel + * @version 2024-1-22 + * @since API 1.1.0 + */ +public abstract class DhApiBeforeDeferredRenderEvent extends DhApiBeforeRenderEvent +{ + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java new file mode 100644 index 000000000..aca5cff1f --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java @@ -0,0 +1,47 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called before Distant Horizons starts the cleanup process done after rendering.
+ * This called after every render pass. + * + * @author James Seibel + * @version 2024-1-31 + * @since API 1.1.0 + */ +public abstract class DhApiBeforeRenderCleanupEvent implements IDhApiEvent +{ + /** Fired before Distant Horizons renders LODs. */ + public abstract void beforeCleanup(DhApiEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam event) { this.beforeCleanup(event); } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java index 5aac32845..b91b0f49b 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java @@ -31,10 +31,10 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp * @version 2023-6-23 * @since API 1.0.0 */ -public abstract class DhApiBeforeRenderEvent implements IDhApiCancelableEvent +public abstract class DhApiBeforeRenderEvent implements IDhApiCancelableEvent { /** Fired before Distant Horizons renders LODs. */ - public abstract void beforeRender(DhApiCancelableEventParam input); + public abstract void beforeRender(DhApiCancelableEventParam event); //=========================// @@ -42,20 +42,6 @@ public abstract class DhApiBeforeRenderEvent implements IDhApiCancelableEvent input) { this.beforeRender(input); } - - - //==================// - // parameter object // - //==================// - - public static class EventParam extends DhApiRenderParam - { - public EventParam(DhApiRenderParam parent) - { - super(parent.mcProjectionMatrix, parent.mcModelViewMatrix, parent.dhProjectionMatrix, parent.dhModelViewMatrix, parent.partialTicks); - } - - } + public final void fireEvent(DhApiCancelableEventParam input) { this.beforeRender(input); } } \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderPassEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderPassEvent.java new file mode 100644 index 000000000..b12784ced --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderPassEvent.java @@ -0,0 +1,54 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called immediately before Distant Horizons starts a rendering pass.
+ * At this point the GL state will be set up for DH to render.
+ * This event cannot be cancelled, use {@link DhApiBeforeRenderEvent} if you want to cancel rendering. + * + * @author James Seibel + * @version 2023-1-31 + * @since API 1.1.0 + * + * @see DhApiBeforeRenderEvent + */ +public abstract class DhApiBeforeRenderPassEvent implements IDhApiEvent +{ + /** + * Fired immediately before Distant Horizons starts a rendering pass.
+ * {@link DhApiRenderParam#renderPass} should either be {@link EDhApiRenderPass#OPAQUE} or {@link EDhApiRenderPass#TRANSPARENT}. + */ + public abstract void beforeRender(DhApiEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam event) { this.beforeRender(event); } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderSetupEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderSetupEvent.java new file mode 100644 index 000000000..4ebb8fe74 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderSetupEvent.java @@ -0,0 +1,50 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called before Distant Horizons has started setting up OpenGL objects for rendering.
+ * If you want to modify already bound DH OpenGL objects try using {@link DhApiBeforeRenderPassEvent}. + * + * @author James Seibel + * @version 2024-1-31 + * @since API 1.1.0 + * + * @see DhApiBeforeRenderPassEvent + */ +public abstract class DhApiBeforeRenderSetupEvent implements IDhApiEvent +{ + /** Fired before Distant Horizons has started setting up OpenGL objects for rendering. */ + public abstract void beforeSetup(DhApiEventParam input); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam input) { this.beforeSetup(input); } + + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeTextureClearEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeTextureClearEvent.java new file mode 100644 index 000000000..ff87569bb --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeTextureClearEvent.java @@ -0,0 +1,49 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called during Distant Horizons rendering setup and immediately
+ * before the render textures are cleared.
+ * Generally the textures cleared are Distant Horizons owned depth and color textures.
+ * Canceling the event will prevent DH from clearing any textures. + * + * @author James Seibel + * @version 2024-1-31 + * @since API 1.1.0 + */ +public abstract class DhApiBeforeTextureClearEvent implements IDhApiCancelableEvent +{ + /** Fired before Distant Horizons clears any textures. */ + public abstract void beforeClear(DhApiCancelableEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiCancelableEventParam input) { this.beforeClear(input); } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiScreenResizeEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiScreenResizeEvent.java new file mode 100644 index 000000000..387981aad --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiScreenResizeEvent.java @@ -0,0 +1,77 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; + +/** + * Called before Distant Horizons starts rendering a buffer.
+ * This event cannot be cancelled, use {@link DhApiBeforeRenderEvent} if you want to cancel rendering. + * + * @author James Seibel + * @version 2023-1-23 + * @since API 1.1.0 + */ +public abstract class DhApiScreenResizeEvent implements IDhApiEvent +{ + /** Fired immediately before Distant Horizons renders any transparent buffers. */ + public abstract void onResize(DhApiEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam event) { this.onResize(event); } + + + //==================// + // parameter object // + //==================// + + public static class EventParam + { + /** Measured in pixels */ + public final int previousWidth; + /** Measured in pixels */ + public final int previousHeight; + + /** Measured in pixels */ + public final int newWidth; + /** Measured in pixels */ + public final int newHeight; + + + public EventParam( + int previousWidth, int previousHeight, + int newWidth, int newHeight) + { + this.previousWidth = previousWidth; + this.previousHeight = previousHeight; + + this.newWidth = newWidth; + this.newHeight = newHeight; + + } + } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/sharedParameterObjects/DhApiRenderParam.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/sharedParameterObjects/DhApiRenderParam.java index 218067ab0..55bd918e0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/sharedParameterObjects/DhApiRenderParam.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/sharedParameterObjects/DhApiRenderParam.java @@ -19,17 +19,35 @@ package com.seibel.distanthorizons.api.methods.events.sharedParameterObjects; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; /** * Contains information relevant to Distant Horizons and Minecraft rendering. * * @author James Seibel - * @version 2022-9-5 + * @version 2024-1-31 * @since API 1.0.0 */ public class DhApiRenderParam { + /** Indicates what render pass DH is currently rendering */ + public final EDhApiRenderPass renderPass; + + /** Indicates how far into this tick the frame is. */ + public final float partialTicks; + + /** + * Indicates DH's near clip plane, measured in blocks. + * Note: this may change based on time, player speed, and other factors. + */ + public final float nearClipPlane; + /** + * Indicates DH's far clip plane, measured in blocks. + * Note: this may change based on time, player speed, and other factors. + */ + public final float farClipPlane; + /** The projection matrix Minecraft is using to render this frame. */ public final Mat4f mcProjectionMatrix; /** The model view matrix Minecraft is using to render this frame. */ @@ -40,23 +58,53 @@ public class DhApiRenderParam /** The model view matrix Distant Horizons is using to render this frame. */ public final Mat4f dhModelViewMatrix; - /** Indicates how far into this tick the frame is. */ - public final float partialTicks; + public final int lightmapBindingIndex = 0; + + // TODO why is this here? wouldn't it make more sense to have this built into the vertex buffer data? + public final int worldYOffset; + //==============// + // constructors // + //==============// + + public DhApiRenderParam(DhApiRenderParam parent) + { + this( + parent.renderPass, + parent.partialTicks, + parent.nearClipPlane, parent.farClipPlane, + parent.mcProjectionMatrix, parent.mcModelViewMatrix, + parent.dhProjectionMatrix, parent.dhModelViewMatrix, + parent.worldYOffset + ); + } + public DhApiRenderParam( + EDhApiRenderPass renderPass, + float newPartialTicks, + float nearClipPlane, float farClipPlane, Mat4f newMcProjectionMatrix, Mat4f newMcModelViewMatrix, Mat4f newDhProjectionMatrix, Mat4f newDhModelViewMatrix, - float newPartialTicks) + int worldYOffset + ) { + this.renderPass = renderPass; + + this.partialTicks = newPartialTicks; + + this.farClipPlane = farClipPlane; + this.nearClipPlane = nearClipPlane; + this.mcProjectionMatrix = newMcProjectionMatrix; this.mcModelViewMatrix = newMcModelViewMatrix; this.dhProjectionMatrix = newDhProjectionMatrix; this.dhModelViewMatrix = newDhModelViewMatrix; - this.partialTicks = newPartialTicks; + this.worldYOffset = worldYOffset; + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index 4b53ffc84..4a81bd1c1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -19,15 +19,20 @@ package com.seibel.distanthorizons.core.api.internal; +import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer; import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.render.DhApiRenderProxy; import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.world.*; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.api.enums.rendering.EDebugRendering; import com.seibel.distanthorizons.api.enums.rendering.ERendererMode; @@ -49,6 +54,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL32; import java.util.HashMap; import java.util.HashSet; @@ -452,19 +458,21 @@ public class ClientApi /** Should be called before {@link ClientApi#renderDeferredLods} */ public void renderLods(IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks) - { this.renderLodLayer(levelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, true); } + { this.renderLodLayer(levelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, false); } /** * Only necessary when Shaders are in use. * Should be called after {@link ClientApi#renderLods} */ public void renderDeferredLods(IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks) - { this.renderLodLayer(levelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, false); } + { this.renderLodLayer(levelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, true); } private void renderLodLayer( IClientLevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, boolean renderingDeferredLayer) { + // logging // + if (ModInfo.IS_DEV_BUILD && !this.configOverrideReminderPrinted && MC.playerExists()) { this.configOverrideReminderPrinted = true; @@ -475,12 +483,45 @@ public class ClientApi MC.sendChatMessage("Here be dragons!"); } - - IProfilerWrapper profiler = MC.getProfiler(); profiler.pop(); // get out of "terrain" profiler.push("DH-RenderLevel"); - + + + + // render parameter setup // + + EDhApiRenderPass renderPass; + if (DhApiRenderProxy.INSTANCE.getDeferTransparentRendering()) + { + if (renderingDeferredLayer) + { + renderPass = EDhApiRenderPass.TRANSPARENT; + } + else + { + renderPass = EDhApiRenderPass.OPAQUE; + } + } + else + { + renderPass = EDhApiRenderPass.OPAQUE_AND_TRANSPARENT; + } + + DhApiRenderParam renderEventParam = + new DhApiRenderParam( + renderPass, + partialTicks, + RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), RenderUtil.getFarClipPlaneDistanceInBlocks(), + mcProjectionMatrix, mcModelViewMatrix, + RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks), RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), + levelWrapper.getMinHeight() + ); + + + + // render validation // + try { if (!RenderUtil.shouldLodsRender(levelWrapper)) @@ -495,21 +536,28 @@ public class ClientApi } IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper); + if (this.rendererDisabledBecauseOfExceptions) + { + return; + } - DhApiRenderParam renderEventParam = - new DhApiRenderParam(mcProjectionMatrix, mcModelViewMatrix, - RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks), - RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), partialTicks); - if (renderingDeferredLayer) + // render pass // + + if (!renderingDeferredLayer) { if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEFAULT) { - this.renderingCancelledForThisFrame = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, new DhApiBeforeRenderEvent.EventParam(renderEventParam)); - if (!this.rendererDisabledBecauseOfExceptions && !this.renderingCancelledForThisFrame) + this.renderingCancelledForThisFrame = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, renderEventParam); + if (!this.renderingCancelledForThisFrame) { - level.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + level.render(renderEventParam, profiler); + } + + if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering()) + { + ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam); } } else if (Config.Client.Advanced.Debugging.rendererMode.get() == ERendererMode.DEBUG) @@ -521,18 +569,23 @@ public class ClientApi } else { - if (!this.rendererDisabledBecauseOfExceptions && !this.renderingCancelledForThisFrame) + boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, renderEventParam); + if (!renderingCancelled) { - level.renderDeferred(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); - - ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, new DhApiAfterRenderEvent.EventParam(renderEventParam)); + level.renderDeferred(renderEventParam, profiler); + } + + + if (DhApi.Delayed.renderProxy.getDeferTransparentRendering()) + { + ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam); } } } catch (Exception e) { this.rendererDisabledBecauseOfExceptions = true; - LOGGER.error("Unexpected Renderer error in " + (renderingDeferredLayer ? "Opaque" : "Transparent") + " stage. Error: " + e.getMessage(), e); + LOGGER.error("Unexpected Renderer error in render pass [" + renderPass + "]. Error: " + e.getMessage(), e); MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!"); MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues."); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java index 86ce44c6e..e041efb21 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EGLProxyContext; @@ -275,10 +276,10 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer //========// @Override - public boolean renderOpaque(LodRenderer renderContext) + public boolean renderOpaque(LodRenderer renderContext, DhApiRenderParam renderEventParam) { boolean hasRendered = false; - renderContext.setupOffset(this.pos); + renderContext.setModelViewMatrixOffset(this.pos, renderEventParam); for (GLVertexBuffer vbo : this.vbos) { if (vbo == null) @@ -299,14 +300,14 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer } @Override - public boolean renderTransparent(LodRenderer renderContext) + public boolean renderTransparent(LodRenderer renderContext, DhApiRenderParam renderEventParam) { boolean hasRendered = false; try { // can throw an IllegalStateException if the GL program was freed before it should've been - renderContext.setupOffset(this.pos); + renderContext.setModelViewMatrixOffset(this.pos, renderEventParam); for (GLVertexBuffer vbo : this.vbosTransparent) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index 4bcd54335..e83aa706f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.level; import com.seibel.distanthorizons.api.enums.rendering.EDebugRendering; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -141,7 +142,7 @@ public class ClientLevelModule implements Closeable return this.ClientRenderStateRef.get() != null; } - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) { ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); if (ClientRenderState == null) @@ -149,10 +150,10 @@ public class ClientLevelModule implements Closeable // either the renderer hasn't been started yet, or is being reloaded return; } - ClientRenderState.renderer.drawLods(ClientRenderState.clientLevelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + ClientRenderState.renderer.drawLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler); } - public void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + public void renderDeferred(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) { ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); if (ClientRenderState == null) @@ -160,7 +161,7 @@ public class ClientLevelModule implements Closeable // either the renderer hasn't been started yet, or is being reloaded return; } - ClientRenderState.renderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + ClientRenderState.renderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler); } public void stopRenderer() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 45ec55f57..a7b235a90 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider; import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataFileHandler; @@ -88,12 +89,12 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel } @Override - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { this.clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } + public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) + { this.clientside.render(renderEventParam, profiler); } @Override - public void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { this.clientside.renderDeferred(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } + public void renderDeferred(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) + { this.clientside.renderDeferred(renderEventParam, profiler); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index bcf47d9cd..d7da78f41 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider; @@ -81,12 +82,12 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS } @Override - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { this.clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } + public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) + { this.clientside.render(renderEventParam, profiler); } @Override - public void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { this.clientside.renderDeferred(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } + public void renderDeferred(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) + { this.clientside.renderDeferred(renderEventParam, profiler); } @Override public void serverTick() { this.chunkToLodBuilder.tick(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java index 003053470..be7040607 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; @@ -30,8 +31,8 @@ public interface IDhClientLevel extends IDhLevel { void clientTick(); - void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); - void renderDeferred(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); + void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler); + void renderDeferred(DhApiRenderParam renderEventParam, IProfilerWrapper profiler); int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java index 0bb40dc82..29e303fbb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.render; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.StatsMap; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; @@ -31,9 +32,9 @@ public abstract class AbstractRenderBuffer implements AutoCloseable // ========== Called by render thread ========== /** @return true if something was rendered, false otherwise */ - public abstract boolean renderOpaque(LodRenderer renderContext); + public abstract boolean renderOpaque(LodRenderer renderContext, DhApiRenderParam renderEventParam); /** @return true if something was rendered, false otherwise */ - public abstract boolean renderTransparent(LodRenderer renderContext); + public abstract boolean renderTransparent(LodRenderer renderContext, DhApiRenderParam renderEventParam); // ========== Called by any thread. (thread safe) ========== diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java index 5a898b657..3c421607d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java @@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; +import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import org.lwjgl.opengl.GL32; @@ -42,7 +43,7 @@ public class DhApiRenderProxy implements IDhApiRenderProxy private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - public int targetFrameBufferOverride = -1; + private boolean deferTransparentRendering = false; @@ -82,29 +83,6 @@ public class DhApiRenderProxy implements IDhApiRenderProxy } - @Override - public DhApiResult getDhFrameBufferId() - { - int activeFrameBuffer = LodRenderer.getActiveFramebufferId(); - return (activeFrameBuffer == -1) ? DhApiResult.createFail("DH's FrameBuffer hasn't been created and/or bound yet.", -1) : DhApiResult.createSuccess(activeFrameBuffer); - } - - - @Override - public DhApiResult setTargetFrameBufferId(int frameBufferId) - { - if (frameBufferId != -1 && !GL32.glIsFramebuffer(frameBufferId)) - { - return DhApiResult.createFail("FrameBufferID ["+frameBufferId+"] isn't a valid FrameBuffer ID."); - } - - this.targetFrameBufferOverride = frameBufferId; - return DhApiResult.createSuccess(); - } - @Override - public DhApiResult getTargetFrameBufferId() { return (this.targetFrameBufferOverride == -1) ? DhApiResult.createSuccess("Default MC FrameBuffer in use.", MC_RENDER.getTargetFrameBuffer()) : DhApiResult.createSuccess("FrameBuffer override active.", this.targetFrameBufferOverride); } - - @Override public DhApiResult getDhDepthTextureId() { @@ -118,4 +96,13 @@ public class DhApiRenderProxy implements IDhApiRenderProxy return (activeTexture == -1) ? DhApiResult.createFail("DH's color texture hasn't been created and/or bound yet.", -1) : DhApiResult.createSuccess(activeTexture); } + + @Override + public void setDeferTransparentRendering(boolean deferTransparentRendering) { this.deferTransparentRendering = deferTransparentRendering; } + @Override + public boolean getDeferTransparentRendering() { return this.deferTransparentRendering; } + + @Override + public float getNearClipPlaneDistanceInBlocks(float partialTicks) { return RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks); } + } 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..ebcc2b1cf 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 @@ -19,7 +19,7 @@ package com.seibel.distanthorizons.core.render; -import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; @@ -225,19 +225,19 @@ public class RenderBufferHandler implements AutoCloseable } } - public void renderOpaque(LodRenderer renderContext) + public void renderOpaque(LodRenderer renderContext, DhApiRenderParam renderEventParam) { //TODO: Directional culling - this.loadedNearToFarBuffers.forEach(loadedBuffer -> loadedBuffer.buffer.renderOpaque(renderContext)); + this.loadedNearToFarBuffers.forEach(loadedBuffer -> loadedBuffer.buffer.renderOpaque(renderContext, renderEventParam)); } - public void renderTransparent(LodRenderer renderContext) + public void renderTransparent(LodRenderer renderContext, DhApiRenderParam renderEventParam) { //TODO: Directional culling ListIterator iter = this.loadedNearToFarBuffers.listIterator(this.loadedNearToFarBuffers.size()); while (iter.hasPrevious()) { LoadedRenderBuffer loadedBuffer = iter.previous(); - loadedBuffer.buffer.renderTransparent(renderContext); + loadedBuffer.buffer.renderTransparent(renderContext, renderEventParam); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java index 5104ee602..363371581 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/texture/DhFramebuffer.java @@ -1,11 +1,11 @@ package com.seibel.distanthorizons.core.render.glObject.texture; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer; import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; import it.unimi.dsi.fastutil.ints.Int2IntMap; import org.lwjgl.opengl.GL32; -// TODO lowercase -public class DhFramebuffer +public class DhFramebuffer implements IDhApiFramebuffer { private final Int2IntMap attachments; private final int maxDrawBuffers; @@ -46,29 +46,24 @@ public class DhFramebuffer // methods // //=========// - public void addDepthAttachment(int texture, EDhDepthBufferFormat depthBufferFormat) + @Override + public void addDepthAttachment(int textureId, boolean isCombinedStencil) { this.bind(); - if (depthBufferFormat.isCombinedStencil()) - { - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_STENCIL_ATTACHMENT, GL32.GL_TEXTURE_2D, texture, 0); - } - else - { - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, texture, 0); - } - + int depthAttachment = isCombinedStencil ? GL32.GL_DEPTH_STENCIL_ATTACHMENT : GL32.GL_DEPTH_ATTACHMENT; + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, depthAttachment, GL32.GL_TEXTURE_2D, textureId, 0); + this.hasDepthAttachment = true; } @Override - public void addColorAttachment(int index, int texture) + public void addColorAttachment(int textureIndex, int textureId) { this.bind(); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0 + index, GL32.GL_TEXTURE_2D, texture, 0); - this.attachments.put(index, texture); + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0 + textureIndex, GL32.GL_TEXTURE_2D, textureId, 0); + this.attachments.put(textureIndex, textureId); } public void noDrawBuffers() @@ -79,7 +74,8 @@ public class DhFramebuffer public void drawBuffers(int[] buffers) { - int[] glBuffers = new int[buffers.length]; int index = 0; + int[] glBuffers = new int[buffers.length]; + int index = 0; if (buffers.length > this.maxDrawBuffers) { @@ -124,7 +120,8 @@ public class DhFramebuffer public void bindAsDrawBuffer() { GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, this.id); } - public void destroyInternal() + @Override + public void destroy() { GL32.glDeleteFramebuffers(this.id); this.id = -1; @@ -138,6 +135,15 @@ public class DhFramebuffer return status; } - public int getId() { return id; } + @Override + public int getId() { return this.id; } + + + + //=============// + // API methods // + //=============// + + public boolean overrideThisFrame() { return true; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index 70597edeb..255653c6a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -19,8 +19,9 @@ package com.seibel.distanthorizons.core.render.renderer; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; -import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.shader.Shader; import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; @@ -29,13 +30,11 @@ import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAtt import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttributePreGL43; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.render.fog.LodFogConfig; import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; -import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants; -public class LodRenderProgram extends ShaderProgram +public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgram { public static final String VERTEX_SHADER_PATH = "shaders/standard.vert"; public static final String VERTEX_CURVE_SHADER_PATH = "shaders/curve.vert"; @@ -68,6 +67,10 @@ public class LodRenderProgram extends ShaderProgram + //=============// + // constructor // + //=============// + // This will bind AbstractVertexAttribute public LodRenderProgram() { @@ -133,38 +136,41 @@ public class LodRenderProgram extends ShaderProgram - // Override ShaderProgram.bind() + //=========// + // methods // + //=========// + + @Override public void bind() { super.bind(); vao.bind(); } - // Override ShaderProgram.unbind() + @Override public void unbind() { super.unbind(); vao.unbind(); } - // Override ShaderProgram.free() + @Override public void free() { vao.free(); super.free(); } - public void bindVertexBuffer(int vbo) - { - vao.bindBufferToAllBindingPoints(vbo); - } + @Override + public void bindVertexBuffer(int vbo) { this.vao.bindBufferToAllBindingPoints(vbo); } - public void unbindVertexBuffer() - { - vao.unbindBuffersFromAllBindingPoint(); - } + public void unbindVertexBuffer() { this.vao.unbindBuffersFromAllBindingPoint(); } - public void fillUniformData(Mat4f combinedMatrix, int lightmapBindPoint, int worldYOffset, float partialTicks) + @Override + public void fillUniformData(DhApiRenderParam renderParameters) { + Mat4f combinedMatrix = new Mat4f(renderParameters.dhProjectionMatrix); + combinedMatrix.multiply(renderParameters.dhModelViewMatrix); + super.bind(); // uniforms @@ -172,21 +178,26 @@ public class LodRenderProgram extends ShaderProgram setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset // setUniform(skyLightUniform, skyLight); - setUniform(lightMapUniform, lightmapBindPoint); + setUniform(lightMapUniform, renderParameters.lightmapBindingIndex); - if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) worldYOffset); + if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) renderParameters.worldYOffset); // Debug setUniform(whiteWorldUniform, Config.Client.Advanced.Debugging.enableWhiteWorld.get()); - // Fog/Clip Uniforms - float dhNearClipDistance = RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks); + // Clip Uniform + float dhNearClipDistance = RenderUtil.getNearClipPlaneDistanceInBlocks(renderParameters.partialTicks); setUniform(clipDistanceUniform, dhNearClipDistance); } - public void setModelPos(Vec3f modelPos) - { - setUniform(modelOffsetUniform, modelPos); - } + @Override + public void setModelOffsetPos(Vec3f modelOffsetPos) { this.setUniform(this.modelOffsetUniform, modelOffsetPos); } + + @Override + public int getId() { return this.id; } + + /** The base DH render program should always render */ + @Override + public boolean overrideThisFrame() { return true; } } 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 6ebacb699..d35085d0d 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 @@ -19,13 +19,21 @@ package com.seibel.distanthorizons.core.render.renderer; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; +import com.seibel.distanthorizons.api.enums.rendering.EFogDrawMode; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.render.AbstractRenderBuffer; +import com.seibel.distanthorizons.core.render.DhApiRenderProxy; import com.seibel.distanthorizons.core.render.RenderBufferHandler; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; @@ -43,6 +51,8 @@ import com.seibel.distanthorizons.core.render.fog.LodFogConfig; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; +import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; +import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3d; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; @@ -87,24 +97,30 @@ public class LodRenderer private int cachedWidth; private int cachedHeight; - // Iris sets this to enable a deferred rendering mode. - // DO NOT SET THIS TO FINAL!!! - private boolean deferTransparentRendering = false; - - - public void setupOffset(DhBlockPos pos) throws IllegalStateException + /** called by each {@link ColumnRenderBuffer} before rendering */ + public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException { Vec3d cam = MC_RENDER.getCameraExactPosition(); Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z)); - if (!GL32.glIsProgram(this.shaderProgram.id)) + + IDhApiShaderProgram shaderProgram = this.lodRenderProgram; + IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); + if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) { - throw new IllegalStateException("No GL program exists with the ID: [" + this.shaderProgram.id + "]. This either means a shader program was freed while it was still in use or was never created."); + shaderProgram = shaderProgramOverride; } - this.shaderProgram.bind(); - this.shaderProgram.setModelPos(modelPos); + if (!GL32.glIsProgram(shaderProgram.getId())) + { + throw new IllegalStateException("No GL program exists with the ID: [" + shaderProgram.getId() + "]. This either means a shader program was freed while it was still in use or was never created."); + } + + shaderProgram.bind(); + shaderProgram.setModelOffsetPos(modelPos); + + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos)); } public void drawVbo(GLVertexBuffer vbo) @@ -113,8 +129,16 @@ public class LodRenderer //// shouldn't be used in production due to the performance hit //if (GL32.glIsBuffer(vbo.getId())) { + IDhApiShaderProgram shaderProgram = this.lodRenderProgram; + IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); + if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) + { + shaderProgram = shaderProgramOverride; + } + + vbo.bind(); - this.shaderProgram.bindVertexBuffer(vbo.getId()); + shaderProgram.bindVertexBuffer(vbo.getId()); GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount() / 4) * 6, // TODO what does the 4 and 6 here represent? this.quadIBO.getType(), 0); vbo.unbind(); @@ -125,7 +149,6 @@ public class LodRenderer // //LOGGER.warn("Unable to draw VBO: "+vbo.getId()); //} } - public Vec3f getLookVector() { return MC_RENDER.getLookAtVector(); } public static class LagSpikeCatcher @@ -160,12 +183,13 @@ public class LodRenderer public final RenderBufferHandler bufferHandler; // The shader program - LodRenderProgram shaderProgram = null; + IDhApiShaderProgram lodRenderProgram = null; + LodFogConfig fogConfig; public QuadElementBuffer quadIBO = null; public boolean isSetupComplete = false; // frameBuffer and texture ID's for this renderer - private DhFramebuffer framebuffer; + private IDhApiFramebuffer framebuffer; /** will be null if MC's framebuffer is being used since MC already has a color texture */ private DhColorTexture nullableColorTexture; private DHDepthTexture depthTexture; @@ -223,18 +247,17 @@ public class LodRenderer /** * This will draw both opaque and transparent LODs if - * {@link LodRenderer#deferTransparentRendering} is disabled, + * {@link DhApiRenderProxy#getDeferTransparentRendering()} is false, * otherwise it will only render opaque LODs. */ public void drawLods( - IClientLevelWrapper clientLevelWrapper, - Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, - float partialTicks, IProfilerWrapper profiler) + IClientLevelWrapper clientLevelWrapper, + DhApiRenderParam renderEventParam, IProfilerWrapper profiler) { this.renderLodPass( clientLevelWrapper, - baseModelViewMatrix, baseProjectionMatrix, - partialTicks, profiler, + renderEventParam, + profiler, false); } @@ -245,28 +268,28 @@ public class LodRenderer * but shouldn't be activated as per deferWaterRendering. */ public void drawDeferredLods( - IClientLevelWrapper clientLevelWrapper, - Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, - float partialTicks, IProfilerWrapper profiler) + IClientLevelWrapper clientLevelWrapper, + DhApiRenderParam renderEventParam, IProfilerWrapper profiler) { this.renderLodPass( clientLevelWrapper, - baseModelViewMatrix, baseProjectionMatrix, - partialTicks, profiler, + renderEventParam, + profiler, true); } private void renderLodPass( IClientLevelWrapper clientLevelWrapper, - Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, - float partialTicks, IProfilerWrapper profiler, + DhApiRenderParam renderEventParam, + IProfilerWrapper profiler, boolean runningDeferredPass) { //====================// // validate rendering // //====================// - if (runningDeferredPass && !this.deferTransparentRendering) + boolean deferTransparentRendering = DhApiRenderProxy.INSTANCE.getDeferTransparentRendering(); + if (runningDeferredPass && !deferTransparentRendering) { return; } @@ -315,12 +338,8 @@ public class LodRenderer } drawSaveGLState.end("drawSaveGLState"); - Mat4f projectionMatrix = RenderUtil.createLodProjectionMatrix(baseProjectionMatrix, partialTicks); - - Mat4f modelViewProjectionMatrix = new Mat4f(projectionMatrix); - modelViewProjectionMatrix.multiply(RenderUtil.createLodModelViewMatrix(baseModelViewMatrix)); - - this.setupGLStateAndRenderObjects(minecraftGlState, profiler, modelViewProjectionMatrix, partialTicks, renderingFirstPass); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderSetupEvent.class, renderEventParam); + this.setupGLStateAndRenderObjects(minecraftGlState, profiler, renderEventParam, renderingFirstPass); lightmap.bind(); if (ENABLE_IBO) @@ -330,7 +349,7 @@ public class LodRenderer if (renderingFirstPass) { - this.bufferHandler.buildRenderListAndUpdateSections(this.getLookVector()); + this.bufferHandler.buildRenderListAndUpdateSections(MC_RENDER.getLookAtVector()); transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled; @@ -356,24 +375,30 @@ public class LodRenderer GL32.glDisable(GL32.GL_BLEND); profiler.popPush("LOD Opaque"); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam); + // TODO: Directional culling - this.bufferHandler.renderOpaque(this); + this.bufferHandler.renderOpaque(this, renderEventParam); if (Config.Client.Advanced.Graphics.Ssao.enabled.get()) { profiler.popPush("LOD SSAO"); - SSAORenderer.INSTANCE.render(minecraftGlState, projectionMatrix, partialTicks); + SSAORenderer.INSTANCE.render(minecraftGlState, renderEventParam.dhProjectionMatrix, renderEventParam.partialTicks); } - profiler.popPush("LOD Fog"); - FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix); - FogShader.INSTANCE.render(partialTicks); + + if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EFogDrawMode.FOG_DISABLED) + { + profiler.popPush("LOD Fog"); + FogShader.INSTANCE.setModelViewProjectionMatrix(renderEventParam.dhModelViewMatrix); + FogShader.INSTANCE.render(renderEventParam.partialTicks); + } //DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker - if (!this.deferTransparentRendering) + if (!deferTransparentRendering && Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) { - this.renderTransparentBuffers(profiler, partialTicks); + this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks); } @@ -395,7 +420,7 @@ public class LodRenderer { profiler.popPush("Debug wireframes"); // Note: this can be very slow if a lot of boxes are being rendered - DebugRenderer.INSTANCE.render(modelViewProjectionMatrix); + DebugRenderer.INSTANCE.render(renderEventParam.dhModelViewMatrix); profiler.popPush("LOD cleanup"); } @@ -405,15 +430,18 @@ public class LodRenderer // Apply to the MC FrameBuffer // //=============================// - profiler.popPush("LOD Apply"); - - GLState dhApplyGlState = new GLState(); - - // Copy the LOD framebuffer to Minecraft's framebuffer - DhApplyShader.INSTANCE.render(partialTicks); - - dhApplyGlState.restore(); - + boolean cancelApplyShader = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeApplyShaderRenderEvent.class, renderEventParam); + if (!cancelApplyShader) + { + profiler.popPush("LOD Apply"); + + GLState dhApplyGlState = new GLState(); + + // Copy the LOD framebuffer to Minecraft's framebuffer + DhApplyShader.INSTANCE.render(renderEventParam.partialTicks); + + dhApplyGlState.restore(); + } } else { @@ -421,7 +449,10 @@ public class LodRenderer // deferred rendering // //====================// - this.renderTransparentBuffers(profiler, partialTicks); + if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) + { + this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks); + } drawLagSpikeCatcher.end("LodTranslucentDraw"); } @@ -434,10 +465,11 @@ public class LodRenderer profiler.popPush("LOD cleanup"); LagSpikeCatcher drawCleanup = new LagSpikeCatcher(); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderEventParam); // GLProxy tasks should be run after all rendering has been done - boolean afterEnabledDeferredPass = this.deferTransparentRendering && !renderingFirstPass; - boolean afterOnlyRenderingPass = !this.deferTransparentRendering && renderingFirstPass; + boolean afterEnabledDeferredPass = deferTransparentRendering && !renderingFirstPass; + boolean afterOnlyRenderingPass = !deferTransparentRendering && renderingFirstPass; if (afterEnabledDeferredPass || afterOnlyRenderingPass) { GLProxy.getInstance().runRenderThreadTasks(); @@ -449,7 +481,13 @@ public class LodRenderer this.quadIBO.unbind(); } - this.shaderProgram.unbind(); + IDhApiShaderProgram shaderProgram = this.lodRenderProgram; + IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); + if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) + { + shaderProgram = shaderProgramOverride; + } + shaderProgram.unbind(); minecraftGlState.restore(); drawCleanup.end("LodDrawCleanup"); @@ -465,18 +503,20 @@ public class LodRenderer } } - private void renderTransparentBuffers(IProfilerWrapper profiler, float partialTicks) + private void renderTransparentBuffers(IProfilerWrapper profiler, DhApiRenderParam renderEventParam, float partialTicks) { - if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) + profiler.popPush("LOD Transparent"); + + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendEquation(GL32.GL_FUNC_ADD); + GL32.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam); + this.bufferHandler.renderTransparent(this, renderEventParam); + GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it... + + + if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EFogDrawMode.FOG_DISABLED) { - profiler.popPush("LOD Transparent"); - - GL32.glEnable(GL32.GL_BLEND); - GL32.glBlendEquation(GL32.GL_FUNC_ADD); - GL32.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); - this.bufferHandler.renderTransparent(this); - GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it... - profiler.popPush("LOD Fog"); FogShader.INSTANCE.render(partialTicks); } @@ -490,8 +530,7 @@ public class LodRenderer private void setupGLStateAndRenderObjects( GLState minecraftGlState, IProfilerWrapper profiler, - Mat4f modelViewProjectionMatrix, - float partialTicks, + DhApiRenderParam renderEventParam, boolean firstPass) { //===================// @@ -513,15 +552,20 @@ public class LodRenderer if (MC_RENDER.getTargetFrameBufferViewportWidth() != this.cachedWidth || MC_RENDER.getTargetFrameBufferViewportHeight() != this.cachedHeight) { - this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth(); - this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight(); - // just resizing the textures doesn't work when Optifine is present, // so recreate the textures with the new size instead - this.createColorAndDepthTextures(this.cachedWidth, this.cachedHeight); + this.createColorAndDepthTextures(); } - this.setActiveFramebufferId(this.framebuffer.getId()); + + IDhApiFramebuffer activeFrameBuffer = this.framebuffer; + IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class); + if (framebufferOverride != null && framebufferOverride.overrideThisFrame()) + { + activeFrameBuffer = framebufferOverride; + } + + this.setActiveFramebufferId(activeFrameBuffer.getId()); this.setActiveDepthTextureId(this.depthTexture.getTextureId()); if (this.nullableColorTexture != null) { @@ -534,30 +578,34 @@ public class LodRenderer this.setActiveColorTextureId(mcColorTextureId); } // Bind LOD frame buffer - this.framebuffer.bind(); + activeFrameBuffer.bind(); - if (this.usingMcFrameBuffer) + boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderEventParam); + if (clearTextures) { - // recreating the GL State at this point is necessary in order to get the correct depth texture - minecraftGlState.saveState(); - if (ENABLE_DUMP_GL_STATE) + if (this.usingMcFrameBuffer && framebufferOverride == null) { - tickLogger.debug("Re-saving GL state due to Optifine presence: " + minecraftGlState); + // recreating the GL State at this point is necessary in order to get the correct depth texture + minecraftGlState.saveState(); + if (ENABLE_DUMP_GL_STATE) + { + tickLogger.debug("Re-saving GL state due to Optifine presence: " + minecraftGlState); + } + + + // Due to using MC/Optifine's framebuffer we need to re-bind the depth texture, + // otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues + activeFrameBuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil()); + + + // don't clear the color texture, that removes the sky + GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); + } + else if (firstPass) + { + GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT); } - - - // Due to using MC/Optifine's framebuffer we need to re-bind the depth texture, - // otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues - this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F); - - - // don't clear the color texture, that removes the sky - GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); - } - else if (firstPass) - { - GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT); } @@ -591,26 +639,33 @@ public class LodRenderer } else { - LodFogConfig newFogConfig = this.shaderProgram.isShaderUsable(); - if (newFogConfig != null) + LodFogConfig newFogConfig = LodFogConfig.generateFogConfig(); // TODO use a config listener instead + if (this.fogConfig == null) { + this.fogConfig = newFogConfig; + } + + if (!this.fogConfig.equals(newFogConfig)) + { + this.fogConfig = newFogConfig; + this.lodRenderProgram.free(); this.lodRenderProgram = new LodRenderProgram(); FogShader.INSTANCE.free(); FogShader.INSTANCE = new FogShader(newFogConfig); } - this.shaderProgram.bind(); + this.lodRenderProgram.bind(); } - /*---------Get required data--------*/ - //int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; - //Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks); + IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); + if (shaderProgramOverride != null) + { + shaderProgramOverride.fillUniformData(renderEventParam); + } - /*---------Fill uniform data--------*/ - this.shaderProgram.fillUniformData(modelViewProjectionMatrix, /*Light map = GL_TEXTURE0*/ 0, - MC.getWrappedClientLevel().getMinHeight(), partialTicks); + this.lodRenderProgram.fillUniformData(renderEventParam); } /** Setup all render objects - MUST be called on the render thread */ @@ -659,9 +714,7 @@ public class LodRenderer } // create and bind the necessary textures - this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth(); - this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight(); - this.createColorAndDepthTextures(this.cachedWidth, this.cachedHeight); + this.createColorAndDepthTextures(); if(this.framebuffer.getStatus() != GL32.GL_FRAMEBUFFER_COMPLETE) { @@ -678,23 +731,45 @@ public class LodRenderer } } /** also binds the new textures to the {@link LodRenderer#framebuffer} */ - private void createColorAndDepthTextures(int width, int height) + private void createColorAndDepthTextures() { - // don't use the cached width/height just in case they haven't been set yet + int oldWidth = this.cachedWidth; + int oldHeight = this.cachedHeight; + this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth(); + this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight(); - this.depthTexture = new DHDepthTexture(width, height, EDhDepthBufferFormat.DEPTH32F); - this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F); + + ApiEventInjector.INSTANCE.fireAllEvents(DhApiScreenResizeEvent.class, + new DhApiScreenResizeEvent.EventParam( + oldWidth, oldHeight, + this.cachedWidth, this.cachedHeight + )); + + + // also update the override if present + IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class); + + this.depthTexture = new DHDepthTexture(this.cachedWidth, this.cachedHeight, EDhDepthBufferFormat.DEPTH32F); + this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil()); + if (framebufferOverride != null) + { + framebufferOverride.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil()); + } // if we are using MC's frame buffer, a color texture is already present and shouldn't need to be bound if (!this.usingMcFrameBuffer) { - this.nullableColorTexture = DhColorTexture.builder().setDimensions(width, height) + this.nullableColorTexture = DhColorTexture.builder().setDimensions(this.cachedWidth, this.cachedHeight) .setInternalFormat(EDhInternalTextureFormat.RGBA8) .setPixelType(EDhPixelType.UNSIGNED_BYTE) .setPixelFormat(EDhPixelFormat.RGBA) .build(); this.framebuffer.addColorAttachment(0, this.nullableColorTexture.getTextureId()); + if (framebufferOverride != null) + { + framebufferOverride.addColorAttachment(0, this.nullableColorTexture.getTextureId()); + } } else { @@ -767,10 +842,10 @@ public class LodRenderer { EVENT_LOGGER.info("Renderer Cleanup Started"); - if (this.shaderProgram != null) + if (this.lodRenderProgram != null) { - this.shaderProgram.free(); - this.shaderProgram = null; + this.lodRenderProgram.free(); + this.lodRenderProgram = null; } if (this.quadIBO != null) @@ -778,7 +853,7 @@ public class LodRenderer // Delete framebuffer, color texture, and depth texture if (this.framebuffer != null && !this.usingMcFrameBuffer) - this.framebuffer.destroyInternal(); + this.framebuffer.destroy(); if (this.nullableColorTexture != null) this.nullableColorTexture.destroy(); if (this.depthTexture != null) From 35af4eaed39aa6047aa2a8bba58e010a8e8fb99a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 1 Feb 2024 20:48:06 -0600 Subject: [PATCH 21/34] Fix debug renderer --- .../distanthorizons/core/render/renderer/LodRenderer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 d35085d0d..672ec1196 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 @@ -419,8 +419,12 @@ public class LodRenderer if (Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) { profiler.popPush("Debug wireframes"); + + Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); + combinedMatrix.multiply(renderEventParam.dhModelViewMatrix); + // Note: this can be very slow if a lot of boxes are being rendered - DebugRenderer.INSTANCE.render(renderEventParam.dhModelViewMatrix); + DebugRenderer.INSTANCE.render(combinedMatrix); profiler.popPush("LOD cleanup"); } From cbc34fad8253e48c6edfa85e57a6c137e7b55b60 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 1 Feb 2024 21:05:27 -0600 Subject: [PATCH 22/34] Add comment about potential Iris file handling --- .../distanthorizons/core/file/AbstractDataSourceHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java index 7aaa93a07..b87b809c5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java @@ -306,7 +306,7 @@ public abstract class AbstractDataSourceHandler Date: Sat, 3 Feb 2024 19:45:15 -0600 Subject: [PATCH 23/34] Swap javax nullable annotations with jetbrains for unimined --- .../core/file/subDimMatching/SubDimensionPlayerData.java | 2 +- .../java/com/seibel/distanthorizons/core/pos/DhBlockPos.java | 2 +- .../core/wrapperInterfaces/world/IClientLevelWrapper.java | 3 +-- .../core/wrapperInterfaces/world/IServerLevelWrapper.java | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java index 766a2d441..e096adfa2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java @@ -26,7 +26,7 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.io.File; /** diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java index 69b2b81ba..7fe2bad0a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.pos; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.util.LodUtil; -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.util.Objects; public class DhBlockPos diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java index 7cc81720e..8ef1e3a01 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java @@ -21,8 +21,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.world; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; /** * @version 2022-9-16 diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java index f2caec056..b6740bb13 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java @@ -19,7 +19,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.world; -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.io.File; public interface IServerLevelWrapper extends ILevelWrapper From 30055805d8fc90687f71aab20ab86f8cbcbc6ba3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 5 Feb 2024 19:21:46 -0600 Subject: [PATCH 24/34] Fix Render Buffer count F3 menu not closing --- .../seibel/distanthorizons/core/render/RenderBufferHandler.java | 2 ++ 1 file changed, 2 insertions(+) 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 ebcc2b1cf..6478ca15f 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 @@ -264,6 +264,8 @@ public class RenderBufferHandler implements AutoCloseable renderSection.dispose(); } } + + this.f3Message.close(); } From bc1a4ec1389aebab233961cfe8e2be8879e15ee8 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 07:17:10 -0600 Subject: [PATCH 25/34] Add Joml Matrix constructor to Mat4f --- .../coreapi/util/math/Mat4f.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java index 74e2c5d99..6e0657244 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java @@ -19,6 +19,8 @@ package com.seibel.distanthorizons.coreapi.util.math; +import org.joml.Matrix4f; + import java.nio.FloatBuffer; /** @@ -73,6 +75,31 @@ public class Mat4f this.m33 = sourceMatrix.m33; } + public Mat4f(Matrix4f sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } + private static float[] convertJomlMatrixToArray(Matrix4f sourceMatrix) + { + FloatBuffer buffer = FloatBuffer.allocate(16); + + buffer.put(bufferIndex(0, 0), sourceMatrix.m00()); + buffer.put(bufferIndex(0, 1), sourceMatrix.m01()); + buffer.put(bufferIndex(0, 2), sourceMatrix.m02()); + buffer.put(bufferIndex(0, 3), sourceMatrix.m03()); + buffer.put(bufferIndex(1, 0), sourceMatrix.m10()); + buffer.put(bufferIndex(1, 1), sourceMatrix.m11()); + buffer.put(bufferIndex(1, 2), sourceMatrix.m12()); + buffer.put(bufferIndex(1, 3), sourceMatrix.m13()); + buffer.put(bufferIndex(2, 0), sourceMatrix.m20()); + buffer.put(bufferIndex(2, 1), sourceMatrix.m21()); + buffer.put(bufferIndex(2, 2), sourceMatrix.m22()); + buffer.put(bufferIndex(2, 3), sourceMatrix.m23()); + buffer.put(bufferIndex(3, 0), sourceMatrix.m30()); + buffer.put(bufferIndex(3, 1), sourceMatrix.m31()); + buffer.put(bufferIndex(3, 2), sourceMatrix.m32()); + buffer.put(bufferIndex(3, 3), sourceMatrix.m33()); + + return buffer.array(); + } + /* Quaternions are not currently needed/implemented public Matrix4float(Quaternion p_i48104_1_) { From f6e2f2f52ac4ffa5dabc280db97202fb566d0406 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 17:48:55 -0600 Subject: [PATCH 26/34] Remove unnecessary warning log and broken asssertions --- .../core/dataObjects/render/ColumnRenderSourceLoader.java | 7 ------- .../transformers/FullDataToRenderDataTransformer.java | 7 ------- 2 files changed, 14 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSourceLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSourceLoader.java index 26e72a894..538dac67d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSourceLoader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSourceLoader.java @@ -55,14 +55,7 @@ public class ColumnRenderSourceLoader switch (dataFileVersion) { case 1: - //LOGGER.info("loading render source "+dataFile.pos); - ParsedColumnData parsedColumnData = readDataV1(inputStream, level.getMinY()); - if (parsedColumnData.isEmpty) - { - LOGGER.warn("Empty render file " + dto.pos); - } - return new ColumnRenderSource(dto.pos, parsedColumnData, level); default: throw new IOException("Invalid Data: The data version [" + dataFileVersion + "] is not supported"); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 9d376799b..6e0c81d27 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -135,11 +135,6 @@ public class FullDataToRenderDataTransformer ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); SingleColumnFullDataAccessor fullArrayView = fullDataSource.get(x, z); convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView); - - if (fullArrayView.doesColumnExist()) - { - LodUtil.assertTrue(columnSource.doesDataPointExist(x, z)); - } } } @@ -193,8 +188,6 @@ public class FullDataToRenderDataTransformer convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView); columnSource.fillDebugFlag(x, z, 1, 1, ColumnRenderSource.DebugSourceFlag.SPARSE); - if (fullArrayView.doesColumnExist()) - LodUtil.assertTrue(columnSource.doesDataPointExist(x, z)); } } } From 9392decd3502c2d1e00cc0085e3156f82b9dfcf5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 19:23:53 -0600 Subject: [PATCH 27/34] 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); - } - //=========// From 1859d0ea96078099c41d1a53ad87df4e6527a735 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 21:39:42 -0600 Subject: [PATCH 28/34] Add IDhApiCullingFrustum --- .../rendering/IDhApiCullingFrustum.java | 58 +++++++++++++++++++ .../coreapi/util/math/Mat4f.java | 16 ++++- .../core/pos/DhFrustumBounds.java | 38 +++++++----- .../core/render/RenderBufferHandler.java | 28 +++++---- 4 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java new file mode 100644 index 000000000..34ab19eb9 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java @@ -0,0 +1,58 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.interfaces.override.rendering; + +import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; +import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; + +/** + * Used to determine if a LOD should be rendered or is outside the + * user's field of view. + * + * @author James Seibel + * @version 2024-2-6 + * @since API 1.1.0 + */ +public interface IDhApiCullingFrustum extends IDhApiOverrideable +{ + + /** + * Called before a render pass is done. + * + * @param worldMinBlockY the lowest block position this level allows. + * @param worldMaxBlockY the highest block position this level allows. + * @param worldViewProjection the projection matrix used in this render pass. + */ + void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection); + + /** + * returns true if the LOD bounds intersect this frustum + * + * @param lodBlockPosMinX this LOD's starting block X position closest to negative infinity + * @param lodBlockPosMinZ this LOD's starting block Z position closest to negative infinity + * @param lodBlockWidth this LOD's width in blocks + * @param lodDetailLevel this LOD's detail level + * + * @see EDhApiDetailLevel + */ + boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java index 6e0657244..9d24e9f41 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.coreapi.util.math; import org.joml.Matrix4f; +import org.joml.Matrix4fc; import java.nio.FloatBuffer; @@ -75,8 +76,8 @@ public class Mat4f this.m33 = sourceMatrix.m33; } - public Mat4f(Matrix4f sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } - private static float[] convertJomlMatrixToArray(Matrix4f sourceMatrix) + public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } + private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix) { FloatBuffer buffer = FloatBuffer.allocate(16); @@ -216,6 +217,17 @@ public class Mat4f floatBuffer.put(bufferIndex(3, 3), this.m33); } + public Matrix4f createJomlMatrix() + { + return new Matrix4f( + this.m00, this.m10, this.m20, this.m30, + this.m01, this.m11, this.m21, this.m31, + this.m02, this.m12, this.m22, this.m32, + this.m03, this.m13, this.m23, this.m33 + ); + } + + private static int bufferIndex(int xIndex, int zIndex) { return (zIndex * 4) + xIndex; 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 39e4234ac..62d3aac75 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 @@ -1,13 +1,15 @@ package com.seibel.distanthorizons.core.pos; -import org.jetbrains.annotations.NotNull; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; +import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Matrix4fc; import org.joml.Vector3f; -public class DhFrustumBounds +public class DhFrustumBounds implements IDhApiCullingFrustum { private final FrustumIntersection frustum; private final Vector3f boundsMin = new Vector3f(); @@ -32,23 +34,24 @@ public class DhFrustumBounds // methods // //=========// - public void updateFrustum(Matrix4fc matWorldViewProjection) + @Override + public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f dhWorldViewProjection) { - this.frustum.set(matWorldViewProjection); + this.worldMinY = worldMinBlockY; + this.worldMaxY = worldMaxBlockY; - Matrix4fc matWorldViewProjectionInv = new Matrix4f(matWorldViewProjection).invert(); + Matrix4f worldViewProjection = new Matrix4f(dhWorldViewProjection.createJomlMatrix()); + this.frustum.set(worldViewProjection); + + Matrix4fc matWorldViewProjectionInv = new Matrix4f(worldViewProjection).invert(); matWorldViewProjectionInv.frustumAabb(this.boundsMin, this.boundsMax); } - /** returns true if the LOD bounds intersect the frustum **/ - public boolean intersects(@NotNull DhLodPos lodBounds) + @Override + public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) { - 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); + Vector3f lodMin = new Vector3f(lodBlockPosMinX, this.worldMinY, lodBlockPosMinZ); + Vector3f lodMax = new Vector3f(lodBlockPosMinX + lodBlockWidth, this.worldMaxY, lodBlockPosMinZ + lodBlockWidth); 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; @@ -57,4 +60,13 @@ public class DhFrustumBounds return this.frustum.testAab(lodMin, lodMax); } + + + //=====================// + // overridable methods // + //=====================// + + @Override + public int getPriority() { return IOverrideInjector.CORE_PRIORITY; } + } 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 c89b85e19..6b29df28d 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 @@ -19,6 +19,8 @@ package com.seibel.distanthorizons.core.render; +import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; @@ -35,6 +37,8 @@ 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.interfaces.dependencyInjection.IOverrideInjector; +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.Matrix4fc; @@ -64,8 +68,6 @@ public class RenderBufferHandler implements AutoCloseable public F3Screen.MultiDynamicMessage f3Message; - private final DhFrustumBounds frustumBounds; - private int visibleBufferCount; private int culledBufferCount; private int shadowVisibleBufferCount; @@ -82,7 +84,12 @@ public class RenderBufferHandler implements AutoCloseable this.lodQuadTree = lodQuadTree; this.culledBufferCount = 0; - this.frustumBounds = new DhFrustumBounds(); + IDhApiCullingFrustum coreFrustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); + if (coreFrustum == null) + { + DhApi.overrides.bind(IDhApiCullingFrustum.class, new DhFrustumBounds()); + } + this.f3Message = new F3Screen.MultiDynamicMessage( () -> @@ -231,15 +238,13 @@ public class RenderBufferHandler implements AutoCloseable // update the frustum if necessary boolean enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); + IDhApiCullingFrustum frustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); if (enableFrustumCulling) { - float worldMinY = clientLevelWrapper.getMinHeight(); - float worldHeight = clientLevelWrapper.getHeight(); + int worldMinY = clientLevelWrapper.getMinHeight(); + int worldHeight = clientLevelWrapper.getHeight(); - this.frustumBounds.worldMinY = worldMinY; - this.frustumBounds.worldMaxY = worldMinY + worldHeight; - - this.frustumBounds.updateFrustum(matWorldViewProjection); + frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection)); } @@ -276,7 +281,10 @@ public class RenderBufferHandler implements AutoCloseable if (enableFrustumCulling) { DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); - if (!this.frustumBounds.intersects(lodBounds)) + int blockMinX = lodBounds.getX().toBlockWidth(); + int blockMinZ = lodBounds.getZ().toBlockWidth(); + int lodBlockWidth = lodBounds.getBlockWidth(); + if (!frustum.intersects(blockMinX, blockMinZ, lodBlockWidth, lodBounds.detailLevel)) { if (isShadowPass) { From 0cfdf8f57e2c031b1423842aa960111f30aa71af Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 21:44:30 -0600 Subject: [PATCH 29/34] rename DhLodPos .getX/Z -> getMinX/Z --- .../seibel/distanthorizons/core/pos/DhLodPos.java | 12 +++++++----- .../core/render/RenderBufferHandler.java | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java index 21273d79a..d6d038b74 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java @@ -55,8 +55,10 @@ public class DhLodPos implements Comparable // getters // //=========// - public DhLodUnit getX() { return new DhLodUnit(this.detailLevel, this.x); } - public DhLodUnit getZ() { return new DhLodUnit(this.detailLevel, this.z); } + /** gets the X position closest to negative infinity */ + public DhLodUnit getMinX() { return new DhLodUnit(this.detailLevel, this.x); } + /** gets the Z position closest to negative infinity */ + public DhLodUnit getMinZ() { return new DhLodUnit(this.detailLevel, this.z); } // Get the width of this pos, measured in the mc block unit. (i.e. detail 0) public int getBlockWidth() { return this.getWidthAtDetail((byte) 0); } @@ -71,10 +73,10 @@ public class DhLodPos implements Comparable public DhBlockPos2D getCenterBlockPos() { return new DhBlockPos2D( - this.getX().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()), - this.getZ().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth())); + this.getMinX().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()), + this.getMinZ().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth())); } - public DhBlockPos2D getCornerBlockPos() { return new DhBlockPos2D(this.getX().toBlockWidth(), this.getZ().toBlockWidth()); } + public DhBlockPos2D getCornerBlockPos() { return new DhBlockPos2D(this.getMinX().toBlockWidth(), this.getMinZ().toBlockWidth()); } /** converts this position to a lower detail level, angled towards the corner position. */ public DhLodPos getCornerLodPos(byte newDetail) 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 6b29df28d..ac06920ff 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 @@ -281,8 +281,8 @@ public class RenderBufferHandler implements AutoCloseable if (enableFrustumCulling) { DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); - int blockMinX = lodBounds.getX().toBlockWidth(); - int blockMinZ = lodBounds.getZ().toBlockWidth(); + int blockMinX = lodBounds.getMinX().toBlockWidth(); + int blockMinZ = lodBounds.getMinZ().toBlockWidth(); int lodBlockWidth = lodBounds.getBlockWidth(); if (!frustum.intersects(blockMinX, blockMinZ, lodBlockWidth, lodBounds.detailLevel)) { From 223326afe2ace97164d5984459ea9e0a2e9e42f5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 6 Feb 2024 21:44:42 -0600 Subject: [PATCH 30/34] Add frustum culling config control to the API --- .../config/client/IDhApiGraphicsConfig.java | 12 ++++++++++++ .../methods/config/client/DhApiGraphicsConfig.java | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java index f31d1fc9b..1fe6f9435 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java @@ -112,6 +112,18 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup // advanced graphic settings // //===========================// + /** + * Sets whether LODs outside the view frustum culling will + * be culled.

+ * + * Disabling this will prevent LODs not rendering on the corner + * of the users vision and may fix issues if LODs appear to + * start/stop rendering incorrectly based on the camera direction, + * but will also reduce FPS. + */ + @Deprecated + IDhApiConfigValue disableFrustumCulling(); + /** * Sets the distance used by the near clip plane to reduce * overdraw.
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java index 985a4b15d..1d969afc5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java @@ -105,9 +105,9 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig // advanced graphic settings // //===========================// -// @Override -// public IDhApiConfigValue getDisableDirectionalCulling() -// { return new DhApiConfigValue(AdvancedGraphics.disableDirectionalCulling); } + @Override + public IDhApiConfigValue disableFrustumCulling() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling); } @Deprecated @Override From 556550fea802c5e7ad526204a40916ba9b698ad0 Mon Sep 17 00:00:00 2001 From: coolGi Date: Wed, 7 Feb 2024 23:23:07 +1030 Subject: [PATCH 31/34] Fixed mod auto-updating on quilt --- .../distanthorizons/core/jar/JarUtils.java | 16 ++++++++++++++-- .../modAccessor/IModChecker.java | 3 +++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java index a0754da3c..3360f35d9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java @@ -19,6 +19,9 @@ package com.seibel.distanthorizons.core.jar; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; +import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -48,11 +51,20 @@ public class JarUtils try { jarFile = new File(JarUtils.class.getProtectionDomain().getCodeSource().getLocation().toURI()); // Always safe - } + } catch (Exception e) { - LOGGER.warn("Unable to get jarFile, Error: "+e.getMessage(), e); + try + { + LOGGER.warn("Unable to get the jar file, trying backup method... Error: "+e.getMessage(), e); + jarFile = SingletonInjector.INSTANCE.get(IModChecker.class).modLocation(ModInfo.ID); + } + catch (Exception f) + { + LOGGER.warn("Backup jar file getter failed. Error: "+f.getMessage(), f); + } } + System.out.println(jarFile); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java index f06113b06..6b007a198 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java @@ -21,6 +21,8 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; +import java.io.File; + /** * Checks if a mod is loaded * @@ -32,4 +34,5 @@ public interface IModChecker extends IBindable /** Checks if a mod is loaded */ boolean isModLoaded(String modid); + File modLocation(String modid); } From 848b75ad7d38a0bf3badafad9e09e645de8828d7 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 7 Feb 2024 07:06:00 -0600 Subject: [PATCH 32/34] Add Lod Shading to the api config --- .../distanthorizons/api/enums/config/ELodShading.java | 7 +++++++ .../interfaces/config/client/IDhApiGraphicsConfig.java | 10 +++++++++- .../methods/config/client/DhApiGraphicsConfig.java | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELodShading.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELodShading.java index 1a2a1d95f..b098bbab0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELodShading.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELodShading.java @@ -32,8 +32,15 @@ public enum ELodShading // when adding items up the API minor version // when removing items up the API major version + /** Uses Minecraft's shading for LODs */ MINECRAFT, + /** + * Simulates Minecraft's shading. + * This is most useful for shaders that disable Minecraft's shading + * but still require shading on LODs. + */ OLD_LIGHTING, + /** LODs will have no shading */ NONE; } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java index 1fe6f9435..4e5fd3acc 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java @@ -120,8 +120,9 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup * of the users vision and may fix issues if LODs appear to * start/stop rendering incorrectly based on the camera direction, * but will also reduce FPS. + * + * @since API 1.1.0 */ - @Deprecated IDhApiConfigValue disableFrustumCulling(); /** @@ -179,4 +180,11 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup */ IDhApiConfigValue lodBias(); + /** + * Determines how LODs should be shaded. + * + * @since API 1.1.0 + */ + IDhApiConfigValue lodShading(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java index 1d969afc5..aded64723 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java @@ -146,6 +146,10 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig public IDhApiConfigValue lodBias() { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.lodBias); } + @Override + public IDhApiConfigValue lodShading() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.lodShading); } + } From 2f4c39885273ed5c4c2a09361ddc5814c93a12b3 Mon Sep 17 00:00:00 2001 From: coolGi Date: Wed, 7 Feb 2024 23:36:59 +1030 Subject: [PATCH 33/34] Removed a forgotten debug log from a previous commit --- .../main/java/com/seibel/distanthorizons/core/jar/JarUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java index 3360f35d9..f607b98fb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java @@ -64,7 +64,6 @@ public class JarUtils LOGGER.warn("Backup jar file getter failed. Error: "+f.getMessage(), f); } } - System.out.println(jarFile); } From 2651e3d43590637914e068e4a53a62b6407ed84d Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 7 Feb 2024 07:34:43 -0600 Subject: [PATCH 34/34] Attempt to reduce queuing duplicate world gen tasks --- .../file/fullDatafile/GeneratedFullDataFileHandler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java index d0a5d79c9..4b18ed3b1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java @@ -187,7 +187,14 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler ArrayList> taskFutureList = new ArrayList<>(); for (DhSectionPos genPos : genPosList) { - // queue each gen task + // try not to re-queue already generating tasks + if (this.generatingDataSourceByPos.containsKey(genPos)) + { + continue; + } + + + // queue each new gen task GenTask genTask = new GenTask(dataSource.getSectionPos(), new WeakReference<>(dataSource)); CompletableFuture worldGenFuture = worldGenQueue.submitGenTask(genPos, dataSource.getDataDetailLevel(), genTask); worldGenFuture.whenComplete((genTaskResult, ex) ->