From 0efa4c3de33b0d2650e0bb99f2e42add066adf6a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jan 2024 19:24:17 -0600 Subject: [PATCH] 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(); + }