Merge branch 'distant-horizons-core-main'

This commit is contained in:
James Seibel
2024-01-21 19:24:17 -06:00
parent 1c90270eb6
commit 0efa4c3de3
22 changed files with 496 additions and 380 deletions
@@ -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<Pair<IClientLevelWrapper, DhChunkPos>, 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 //
//=================//
@@ -573,6 +573,7 @@ public class Config
.setPerformance(EConfigEntryPerformance.NONE)
.build();
@Deprecated // TODO remove failed experiment
public static ConfigEntry<Boolean> seamlessOverdraw = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment(""
@@ -274,27 +274,6 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
// 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<IDhClientLevel>
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<IDhClientLevel>
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<IDhClientLevel>
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);
}
@@ -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)
{
@@ -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);
}
}
@@ -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
@@ -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<BufferQuad> 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<BufferQuad> 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<BufferQuad> 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
}
@@ -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.
}
}
@@ -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()
@@ -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); }
@@ -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(); }
@@ -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);
@@ -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;
@@ -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
@@ -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);
});
}
@@ -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);
@@ -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()
@@ -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.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).build());
@@ -48,7 +50,21 @@ public class DefaultLodVertexFormats
public static final LodVertexFormat POSITION_COLOR_TEX_LIGHTMAP = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>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.<LodVertexFormatElement>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.<LodVertexFormatElement>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());
}
@@ -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;
@@ -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++)
@@ -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;
*
* <strong>DataPoint Format: </strong><br>
* <code>
* GM: generation mode <br>
* BM: block material id <br>
* A: color alpha <br>
* R: color red <br>
* G: color green <br>
@@ -46,7 +44,7 @@ import java.util.Arrays;
* SL: sky light <br>
*
* =======Bit layout======= <br>
* _ GM GM GM A A A A | <br>
* BM BM BM BM A A A A | <br>
* R R R R R R R R | <br>
* G G G G G G G G | <br>
* B B B B B B B B | <br><br>
@@ -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);
}
}
@@ -39,4 +39,6 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper
int getLightEmission();
byte getIrisBlockMaterialId();
}