# Conflicts:
#	common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java
#	common/src/main/java/com/seibel/distanthorizons/common/commands/PregenCommand.java
#	common/src/main/java/com/seibel/distanthorizons/common/render/openGl/GlDhTerrainShaderProgram.java
This commit is contained in:
Vojtěch Šokala
2026-03-15 15:49:41 +01:00
24 changed files with 178 additions and 285 deletions
@@ -18,6 +18,8 @@ import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
import com.seibel.distanthorizons.core.jar.ModJarInfo;
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
import com.seibel.distanthorizons.core.render.renderer.StubDebugWireframeRenderer;
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -140,13 +142,14 @@ public abstract class AbstractModInitializer
this.initConfig();
this.postInit();
this.postServerInit();
#if MC_VER > MC_1_12_2
this.commandInitializer.onServerReady();
#endif
this.checkForUpdates();
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.#if MC_VER <= MC_1_12_2 getDataDirectory() #else getServerDirectory() #endif);
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory());
});
}
@@ -231,7 +234,10 @@ public abstract class AbstractModInitializer
}
private void postClientInit() { DependencySetup.setRenderingApiBindings(); }
private void postServerInit()
{
SingletonInjector.INSTANCE.bind(AbstractDebugWireframeRenderer.class, new StubDebugWireframeRenderer());
}
//endregion
@@ -1,144 +1,36 @@
package com.seibel.distanthorizons.common.commands;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.generation.PregenManager;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
#if MC_VER <= MC_1_12_2
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.Entity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.WorldServer;
#else
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.generation.PregenManager;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.world.DhServerWorld;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.DimensionArgument;
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
import net.minecraft.server.level.ColumnPos;
import net.minecraft.server.level.ServerLevel;
import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
#endif
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
public class PregenCommand #if MC_VER > MC_1_12_2 extends AbstractCommand #endif
public class PregenCommand extends AbstractCommand
{
#if MC_VER <= MC_1_12_2
private static final PregenManager pregenManager = new PregenManager();
#else
private final PregenManager pregenManager = new PregenManager();
#endif
#if MC_VER <= MC_1_12_2
public void execute(MinecraftServer server, ICommandSender sender, String[] args)
private PregenManager getPregenManager()
{
if (args.length < 2)
{
sender.sendMessage(new TextComponentString("Usage: /dh pregen <status|start|stop>"));
return;
}
switch (args[1])
{
case "status":
{
String statusString = this.pregenManager.getStatusString();
sender.sendMessage(new TextComponentString(
statusString != null ? statusString : "Pregen is not running"));
break;
}
case "start":
{
if (args.length < 5)
{
sender.sendMessage(new TextComponentString("Usage: /dh pregen start <dimension> <x> <z> <chunkRadius>"));
return;
}
if (!Config.Common.WorldGenerator.enableDistantGeneration.get())
{
sender.sendMessage(new TextComponentString("Warning: Distant generation is disabled. Enable it in config for pregen to work."));
return;
}
try
{
String dimensionName = args[2];
int x = Integer.parseInt(args[3]);
int z = Integer.parseInt(args[4]);
int chunkRadius = args.length >= 6 ? Integer.parseInt(args[5]) : 32;
// find the world by dimension name
WorldServer world = null;
for (WorldServer w : server.worlds)
{
if (w.provider.getDimensionType().getName().equals(dimensionName))
{
world = w;
break;
}
}
if (world == null)
{
sender.sendMessage(new TextComponentString("Unknown dimension: " + dimensionName));
return;
}
sender.sendMessage(new TextComponentString("Starting pregen. Progress will be in the server console."));
final ICommandSender finalSender = sender;
CompletableFuture<Void> future = this.pregenManager.startPregen(
ServerLevelWrapper.getWrapper(world),
new DhBlockPos2D(x, z),
chunkRadius
);
future.whenComplete((result, throwable) -> {
if (throwable instanceof CancellationException)
{
finalSender.sendMessage(new TextComponentString("Pregen is cancelled"));
return;
}
else if (throwable != null)
{
finalSender.sendMessage(new TextComponentString("Pregen failed: " + throwable.getMessage()));
return;
}
finalSender.sendMessage(new TextComponentString("Pregen is complete"));
});
}
catch (NumberFormatException e)
{
sender.sendMessage(new TextComponentString("Invalid number format"));
}
break;
}
case "stop":
{
CompletableFuture<Void> runningPregen = this.pregenManager.getRunningPregen();
if (runningPregen == null)
{
sender.sendMessage(new TextComponentString("Pregen is not running"));
return;
}
runningPregen.cancel(true);
break;
}
default:
sender.sendMessage(new TextComponentString("Unknown subcommand: " + args[1]));
}
DhServerWorld world = (DhServerWorld) Objects.requireNonNull(SharedApi.getAbstractDhWorld());
return world.getPregenManager();
}
#else
@Override
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{
@@ -163,7 +55,7 @@ public class PregenCommand #if MC_VER > MC_1_12_2 extends AbstractCommand #endif
private int pregenStatus(CommandContext<CommandSourceStack> c)
{
String statusString = this.pregenManager.getStatusString();
String statusString = this.getPregenManager().getStatusString();
//noinspection ReplaceNullCheck
if (statusString != null)
{
@@ -183,7 +75,7 @@ public class PregenCommand #if MC_VER > MC_1_12_2 extends AbstractCommand #endif
ColumnPos origin = ColumnPosArgument.getColumnPos(c, "origin");
int chunkRadius = getInteger(c, "chunkRadius");
CompletableFuture<Void> future = this.pregenManager.startPregen(
CompletableFuture<Void> future = this.getPregenManager().startPregen(
ServerLevelWrapper.getWrapper(level),
new DhBlockPos2D(#if MC_VER >= MC_1_19_2 origin.x(), origin.z() #else origin.x, origin.z #endif),
chunkRadius
@@ -209,7 +101,7 @@ public class PregenCommand #if MC_VER > MC_1_12_2 extends AbstractCommand #endif
private int pregenStop(CommandContext<CommandSourceStack> c)
{
CompletableFuture<Void> runningPregen = this.pregenManager.getRunningPregen();
CompletableFuture<Void> runningPregen = this.getPregenManager().getRunningPregen();
if (runningPregen == null)
{
return this.sendFailureResponse(c, "Pregen is not running");
@@ -218,5 +110,5 @@ public class PregenCommand #if MC_VER > MC_1_12_2 extends AbstractCommand #endif
runningPregen.cancel(true);
return 1;
}
#endif
}
@@ -146,7 +146,7 @@ public class BlazeDebugWireframeRenderer extends AbstractDebugWireframeRenderer
RenderPipeline.Builder pipelineBuilder = RenderPipeline.builder();
{
pipelineBuilder.withCull(false);
pipelineBuilder.withDepthWrite(false);
pipelineBuilder.withDepthWrite(true);
pipelineBuilder.withDepthTestFunction(DepthTestFunction.LESS_DEPTH_TEST);
pipelineBuilder.withColorWrite(true);
pipelineBuilder.withoutBlend();
@@ -291,7 +291,11 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
}
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
if (boxGroup.size() != 0)
{
// trigger a box change to make sure the initial data is uploaded
boxGroup.triggerBoxChange();
}
long id = boxGroup.getId();
if (this.boxGroupById.containsKey(id))
@@ -495,7 +499,7 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
{
this.renderBoxGroupInstanced(renderPass, renderEventParam, boxGroup, camPos, profiler);
this.renderBoxGroupInstanced(renderPass, renderEventParam, boxGroup, profiler);
}
profiler.pop(); // resource path
@@ -534,7 +538,7 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
private void renderBoxGroupInstanced(
RenderPass renderPass, RenderParams renderEventParam,
RenderableBoxGroup boxGroup, Vec3d camPos,
RenderableBoxGroup boxGroup,
IProfilerWrapper profiler)
{
// update instance data //
@@ -568,7 +572,7 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
renderPass.drawIndexed(
/*indexStart*/ 0,
/*firstIndex*/0,
/*indexCount*/container.uploadedBoxCount * 24, // TODO?
/*indexCount*/container.uploadedBoxCount * 36, // 36 = 6 faces * 6 verticies per face
/*instanceCount*/1);
}
@@ -8,16 +8,21 @@ public class BlazeDhMetaRenderer {}
import com.mojang.blaze3d.textures.GpuTexture;
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhApplyRenderer;
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.RenderParams;
import com.seibel.distanthorizons.core.util.ColorUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
import net.minecraft.client.Minecraft;
import java.awt.*;
public class BlazeDhMetaRenderer implements IDhMetaRenderer
{
public static final BlazeDhMetaRenderer INSTANCE = new BlazeDhMetaRenderer();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private BlazeDhApplyRenderer applyRenderer;
@@ -79,12 +84,10 @@ public class BlazeDhMetaRenderer implements IDhMetaRenderer
@Override
public void clearDhDepthAndColorTextures(RenderParams renderParams)
{
// TODO use for clear color
//IMinecraftRenderWrapper r;
//r.getSkyColor()
this.dhDepthTextureWrapper.clearDepth(1.0f);
this.dhColorTextureWrapper.clearColor(ColorUtil.argbToInt(1, 1, 1, 1));
Color color = MC_RENDER.getSkyColor();
this.dhColorTextureWrapper.clearColor(ColorUtil.toColorInt(color));
}
//endregion
@@ -33,7 +33,7 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadElementBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadIndexBuffer;
import com.seibel.distanthorizons.core.render.RenderParams;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
@@ -88,7 +88,7 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
{
return;
}
this.init = true; // todo only set when succeeded (in case of exception)
VertexFormat vertexFormat = VertexFormat.builder()
@@ -133,6 +133,8 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
pipelineBuilder.withBlend(BlendFunction.TRANSLUCENT);
this.transparentPipeline = pipelineBuilder.build();
}
this.init = true;
}
//endregion
@@ -264,7 +266,7 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
if (this.indexBuffer == null)
{
ByteBuffer buffer = MemoryUtil.memAlloc(LodQuadBuilder.getMaxBufferByteSize() * GLEnums.getTypeSize(GL32.GL_UNSIGNED_INT) * 6);
GlQuadElementBuffer.buildBuffer(LodQuadBuilder.getMaxBufferByteSize(), buffer, GL32.GL_UNSIGNED_INT);
GlQuadIndexBuffer.buildBuffer(LodQuadBuilder.getMaxBufferByteSize(), buffer, GL32.GL_UNSIGNED_INT);
// create buffer if needed
@@ -84,14 +84,10 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
//===========================//
//region
@Override
public void updateVertexData(List<DhApiRenderableBox> uploadBoxList)
{
int boxCount = uploadBoxList.size();
if (boxCount == 0)
{
return; // TODO done just to fix a buffer empty crash
}
// recreate the data arrays if their size is different
if (this.uploadedBoxCount != boxCount)
@@ -183,20 +179,19 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
this.vertexBuffer.put(a);
this.vertexBuffer.put(box.material);
// TODO make sure this all is a multiple of 4 like LodQuadBuilder (might cause issues with AMD/Mac otherwise)
}
}
this.vertexBuffer.flip();
this.indexBuffer.flip();
this.state = BlazeGenericObjectVertexContainer.EState.READY_TO_UPLOAD;
}
private int vertexBufferSize()
{
int faceCount = this.uploadedBoxCount * 6;
int vertexCount = faceCount * 6;
// minimum of 1 box to prevent trying to create a buffer of size 0
int boxCount = Math.max(this.uploadedBoxCount, 1);
int faceCount = boxCount * 6; // 6 faces on a cube
int vertexCount = faceCount * 6; // 6 vertices per cube
int byteSize = vertexCount * 3 * Float.BYTES; // x,y,z
byteSize += vertexCount * 4; // r,g,b,a
@@ -205,11 +200,15 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
}
private int indexBufferSize()
{
int quadCount = this.uploadedBoxCount * 36;
int byteSize = quadCount * GLEnums.getTypeSize(GL32.GL_UNSIGNED_INT) * 6;
// minimum of 1 box to prevent trying to create a buffer of size 0
int boxCount = Math.max(this.uploadedBoxCount, 1);
int quadCount = boxCount * 6 * 6; // 6 faces with 6 vertices each
int byteSize = quadCount * GLEnums.getTypeSize(GL32.GL_UNSIGNED_INT);
return byteSize;
}
@Override
public void uploadDataToGpu()
{
// vertex
@@ -245,8 +244,6 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
COMMAND_ENCODER.writeToBuffer(bufferSlice, this.indexBuffer);
}
this.state = EState.RENDER;
}
private String getVertexBufferName() { return "distantHorizons:GenericVertexBuffer"; }
private String getIndexBufferName() { return "distantHorizons:GenericIndexBuffer"; }
@@ -263,7 +260,7 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
@Override
public void close()
{
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("BlazeGenericObjectVertexContainer close", () ->
{
if (this.vboGpuBuffer != null)
{
@@ -14,28 +14,29 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import org.jetbrains.annotations.NotNull;
/**
* @see LodQuadBuilder
*/
@SuppressWarnings("DataFlowIssue") // ignore null setter warnings in the static constructor (those will only be null if the render API is GL and in that case we should never use these objects)
public class BlazeDhVertexFormatUtil
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
@NotNull public static final VertexFormatElement SCREEN_POS;
@NotNull public static final VertexFormatElement RGBA_FLOAT_COLOR;
public static final VertexFormatElement SCREEN_POS;
public static final VertexFormatElement RGBA_FLOAT_COLOR;
public static final VertexFormatElement SHORT_XYZ_POS;
public static final VertexFormatElement BYTE_PAD;
@NotNull public static final VertexFormatElement SHORT_XYZ_POS;
@NotNull public static final VertexFormatElement BYTE_PAD;
/** contains light and micro-offset */
public static final VertexFormatElement META;
public static final VertexFormatElement RGBA_UBYTE_COLOR;
public static final VertexFormatElement IRIS_MATERIAL;
public static final VertexFormatElement IRIS_NORMAL;
@NotNull public static final VertexFormatElement META;
@NotNull public static final VertexFormatElement RGBA_UBYTE_COLOR;
@NotNull public static final VertexFormatElement IRIS_MATERIAL;
@NotNull public static final VertexFormatElement IRIS_NORMAL;
public static final VertexFormatElement FLOAT_XYZ_POS;
@NotNull public static final VertexFormatElement FLOAT_XYZ_POS;
@@ -84,6 +85,7 @@ public class BlazeDhVertexFormatUtil
}
else
{
// set to null so we can fail fast with a null pointer if we ever attempt to incorrectly use these
SCREEN_POS = null;
RGBA_FLOAT_COLOR = null;
@@ -20,7 +20,7 @@
package com.seibel.distanthorizons.common.render.openGl;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLElementBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLIndexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.shader.GlShaderProgram;
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlAbstractVertexAttribute;
@@ -53,7 +53,7 @@ public class GlDhDebugWireframeRenderer extends AbstractDebugWireframeRenderer
// rendering setup
private GlShaderProgram basicShader;
private GLVertexBuffer vertexBuffer;
private GLElementBuffer indexBuffer;
private GLIndexBuffer indexBuffer;
private GlAbstractVertexAttribute va;
private boolean init = false;
@@ -140,7 +140,7 @@ public class GlDhDebugWireframeRenderer extends AbstractDebugWireframeRenderer
boxOutlineBuffer.order(ByteOrder.nativeOrder());
boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES);
boxOutlineBuffer.rewind();
this.indexBuffer = new GLElementBuffer(false);
this.indexBuffer = new GLIndexBuffer(false);
this.indexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
}
@@ -8,7 +8,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiTextureCreatedParam;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDhFramebuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadElementBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadIndexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.texture.*;
import com.seibel.distanthorizons.common.render.openGl.postProcessing.apply.GlDhApplyShader;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
@@ -242,7 +242,7 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
LOGGER.info("Setting up renderer");
GlDhTerrainShaderProgram.INSTANCE.quadIBO = new GlQuadElementBuffer();
GlDhTerrainShaderProgram.INSTANCE.quadIBO = new GlQuadIndexBuffer();
GlDhTerrainShaderProgram.INSTANCE.quadIBO.reserve(LodQuadBuilder.getMaxBufferByteSize());
@@ -2,6 +2,7 @@ package com.seibel.distanthorizons.common.render.openGl;
import com.seibel.distanthorizons.common.render.openGl.generic.GlGenericObjectRenderer;
import com.seibel.distanthorizons.common.render.openGl.generic.GlGenericObjectVertexContainer;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLState;
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDummyUniformData;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.render.openGl.postProcessing.fade.GlDhFarFadeRenderer;
@@ -44,6 +45,15 @@ public class GlDhRenderApiDefinition extends AbstractDhRenderApiDefinition
@Override public IDhVanillaFadeRenderer getVanillaFadeRenderer() { return GlVanillaFadeRenderer.INSTANCE; }
@Override public IDhTestTriangleRenderer getTestTriangleRenderer() { return GlTestTriangleRenderer.INSTANCE; }
@Override
public void bindRenderers()
{
try (GLState state = new GLState())
{
super.bindRenderers();
}
}
//endregion
@@ -1,22 +1,3 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.render.openGl;
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram;
@@ -25,7 +6,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadElementBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadIndexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.shader.GlShaderProgram;
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlAbstractVertexAttribute;
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlVertexAttributePostGL43;
@@ -55,7 +36,7 @@ import org.lwjgl.opengl.GL32;
/**
* Handles rendering the normal LOD terrain.
* @see LodQuadBuilder
* @see LodQuadBuilder
*/
public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiShaderProgram, IDhTerrainRenderer
{
@@ -71,7 +52,7 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
private boolean init = false;
public GlQuadElementBuffer quadIBO = null;
public GlQuadIndexBuffer quadIBO = null;
public GlAbstractVertexAttribute vao;
// uniforms //
@@ -118,7 +99,11 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
public void init()
{
if (this.init) return;
if (this.init)
{
return;
}
this.uCombinedMatrix = this.getUniformLocation("uCombinedMatrix");
this.uModelOffset = this.getUniformLocation("uModelOffset");
@@ -171,6 +156,7 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
throw e;
}
// unbinding here is necessary to fix an issue when running on Legacy GL
this.vao.unbind();
this.init = true;
@@ -216,7 +202,7 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
combinedMatrix.multiply(renderParameters.dhModelViewMatrix);
super.bind();
// uniforms
this.setUniform(this.uCombinedMatrix, combinedMatrix);
this.setUniform(this.uMircoOffset, 0.01f); // 0.01 block offset
@@ -394,4 +380,4 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
}
}
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLElementBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLIndexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.config.Config;
@@ -91,7 +91,7 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
private IDhApiGenericObjectShaderProgram instancedShaderProgram;
private IDhApiGenericObjectShaderProgram directShaderProgram;
private GLVertexBuffer boxVertexBuffer;
private GLElementBuffer boxIndexBuffer;
private GLIndexBuffer boxIndexBuffer;
private boolean instancedRenderingAvailable;
private boolean vertexAttribDivisorSupported;
@@ -232,7 +232,7 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
ByteBuffer solidIndexBuffer = MemoryUtil.memAlloc(BOX_INDICES.length * Integer.BYTES);
solidIndexBuffer.asIntBuffer().put(BOX_INDICES);
solidIndexBuffer.rewind();
this.boxIndexBuffer = new GLElementBuffer(false);
this.boxIndexBuffer = new GLIndexBuffer(false);
this.boxIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
this.boxIndexBuffer.bind();
MemoryUtil.memFree(solidIndexBuffer);
@@ -361,6 +361,11 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
}
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
if (boxGroup.size() != 0)
{
// trigger a box change to make sure the initial data is uploaded
boxGroup.triggerBoxChange();
}
long id = boxGroup.getId();
@@ -105,10 +105,9 @@ public class GlGenericObjectVertexContainer implements IDhGenericObjectVertexBuf
this.materialData[i] = box.material;
}
this.state = GlGenericObjectVertexContainer.EState.READY_TO_UPLOAD;
}
@Override
public void uploadDataToGpu()
{
this.tryCreateBuffers();
@@ -128,8 +127,6 @@ public class GlGenericObjectVertexContainer implements IDhGenericObjectVertexBuf
// Upload materials
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.material);
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.materialData, GL32.GL_DYNAMIC_DRAW);
this.state = EState.RENDER;
}
/** needs to be done on the render thread */
private void tryCreateBuffers()
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLState;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -78,7 +79,7 @@ public class GLBuffer implements AutoCloseable
static { CLEANUP_THREAD.execute(() -> runPhantomReferenceCleanupLoop()); }
public GLBuffer(boolean isBufferStorage) { this.create(isBufferStorage); }
public GLBuffer(boolean isBufferStorage) { this.destroyOldAndCreate(isBufferStorage); }
//endregion
@@ -104,7 +105,7 @@ public class GLBuffer implements AutoCloseable
//====================//
//region
protected void create(boolean asBufferStorage)
protected void destroyOldAndCreate(boolean asBufferStorage)
{
if (!GLProxy.runningOnRenderThread())
{
@@ -112,10 +113,9 @@ public class GLBuffer implements AutoCloseable
}
// destroy the old buffer if one is present
// (as of 2024-12-31 James didn't see this happen, but just in case)
if (this.id != 0)
{
destroyBufferIdAsync(this.id);
destroyBufferIdNow(this.id);
}
this.id = GLMC.glGenBuffers();
@@ -136,13 +136,19 @@ public class GLBuffer implements AutoCloseable
return;
}
destroyBufferIdAsync(this.id);
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(this.id); });
this.id = 0;
this.size = 0;
}
private static void destroyBufferIdAsync(int id)
private static void destroyBufferIdNow(int id)
{
// only delete valid buffers
if (id == 0)
{
return;
}
// remove and clear the phantom reference if present
if (BUFFER_ID_TO_PHANTOM.containsKey(id))
{
@@ -157,21 +163,18 @@ public class GLBuffer implements AutoCloseable
BUFFER_ID_TO_PHANTOM.remove(id);
}
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
// destroy the buffer if it exists,
// the buffer may not exist if the destroy method is called twice
if (GL32.glIsBuffer(id))
{
// destroy the buffer if it exists,
// the buffer may not exist if the destroy method is called twice
if (GL32.glIsBuffer(id))
GLMC.glDeleteBuffers(id);
bufferCount.decrementAndGet();
if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get())
{
GLMC.glDeleteBuffers(id);
bufferCount.decrementAndGet();
if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get())
{
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
}
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
}
});
}
}
//endregion
@@ -202,36 +205,41 @@ public class GLBuffer implements AutoCloseable
return;
}
// make sure the buffer is ready for uploading
this.createOrChangeBufferTypeForUpload(uploadMethod);
switch (uploadMethod)
// GLState to prevent issues with corrupting the global GL state.
// This can happen especially on legacy GL for MC 1.16.5, creating a black screen.
// Maybe this will also fix random crashing on Mac?
try(GLState state = new GLState())
{
//case NONE:
// return;
case AUTO:
LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!");
case BUFFER_STORAGE:
this.uploadBufferStorage(bb, bufferHint);
break;
case DATA:
this.uploadBufferData(bb, bufferHint);
break;
case SUB_DATA:
this.uploadSubData(bb, maxExpansionSize, bufferHint);
break;
default:
LodUtil.assertNotReach("Unknown GpuUploadMethod!");
// make sure the buffer is ready for uploading
this.createOrChangeBufferTypeForUpload(uploadMethod);
switch (uploadMethod)
{
case AUTO:
LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!");
case BUFFER_STORAGE:
this.uploadBufferStorage(bb);
break;
case DATA:
this.uploadBufferData(bb, bufferHint);
break;
case SUB_DATA:
this.uploadSubData(bb, maxExpansionSize, bufferHint);
break;
default:
LodUtil.assertNotReach("Unknown GpuUploadMethod!");
}
}
}
/** Requires the buffer to be bound */
protected void uploadBufferStorage(ByteBuffer bb, int bufferStorageHint)
protected void uploadBufferStorage(ByteBuffer bb)
{
LodUtil.assertTrue(this.bufferStorage, "Buffer is not bufferStorage but its trying to use bufferStorage upload method!");
int bbSize = bb.limit() - bb.position();
this.destroyAsync();
this.create(true);
this.destroyOldAndCreate(true);
this.bind();
GL44.glBufferStorage(this.getBufferBindingTarget(), bb, 0);
this.size = bbSize;
@@ -300,8 +308,8 @@ public class GLBuffer implements AutoCloseable
{
// recreate if the buffer storage type changed
this.bind();
this.destroyAsync();
this.create(uploadMethod.useBufferStorage);
destroyBufferIdNow(this.id);
this.destroyOldAndCreate(uploadMethod.useBufferStorage);
this.bind();
}
else
@@ -310,7 +318,7 @@ public class GLBuffer implements AutoCloseable
// This can happen if the buffer was deleted previously.
if (this.id == 0)
{
this.create(this.bufferStorage);
this.destroyOldAndCreate(this.bufferStorage);
}
this.bind();
@@ -346,7 +354,7 @@ public class GLBuffer implements AutoCloseable
if (PHANTOM_TO_BUFFER_ID.containsKey(phantomRef))
{
int id = PHANTOM_TO_BUFFER_ID.get(phantomRef);
destroyBufferIdAsync(id);
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer phantom destroy", () -> { destroyBufferIdNow(id); });
//LOGGER.warn("Buffer Phantom collected, ID: ["+id+"]");
}
@@ -22,13 +22,12 @@ package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
import org.lwjgl.opengl.GL32;
/**
* This is a container for a OpenGL
* VBO (Vertex Buffer Object).
* AKA the GLElementBuffer
*
* @author James Seibel
* @version 11-20-2021
*/
public class GLElementBuffer extends GLBuffer
public class GLIndexBuffer extends GLBuffer
{
/**
* When uploading to a buffer that is too small, recreate it this many times
@@ -39,7 +38,7 @@ public class GLElementBuffer extends GLBuffer
protected int type = GL32.GL_UNSIGNED_INT;
public int getType() { return type; }
public GLElementBuffer(boolean isBufferStorage)
public GLIndexBuffer(boolean isBufferStorage)
{
super(isBufferStorage);
}
@@ -52,9 +51,6 @@ public class GLElementBuffer extends GLBuffer
}
@Override
public int getBufferBindingTarget()
{
return GL32.GL_ELEMENT_ARRAY_BUFFER;
}
public int getBufferBindingTarget() { return GL32.GL_ELEMENT_ARRAY_BUFFER; }
}
@@ -28,8 +28,8 @@ import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
/** AKA Index Buffer TODO RENAME */
public class GlQuadElementBuffer extends GLElementBuffer
/** aka GlQuadElementBuffer */
public class GlQuadIndexBuffer extends GLIndexBuffer
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
@@ -40,7 +40,7 @@ public class GlQuadElementBuffer extends GLElementBuffer
//=============//
//region
public GlQuadElementBuffer() { super(false); }
public GlQuadIndexBuffer() { super(false); }
public void reserve(int quadCount)
{
@@ -168,7 +168,7 @@ public class GlVanillaFadeRenderer implements IDhVanillaFadeRenderer
profiler.popPush("Vanilla Fade Apply");
GlDhFarFadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
GlDhFarFadeApplyShader.INSTANCE.readFramebuffer = GlDhFarFadeShader.INSTANCE.frameBuffer;
GlDhFarFadeApplyShader.INSTANCE.readFramebuffer = GlDhVanillaFadeShader.INSTANCE.frameBuffer;
GlDhFarFadeApplyShader.INSTANCE.drawFramebuffer = MC_RENDER.getTargetFramebuffer();
GlDhFarFadeApplyShader.INSTANCE.render(renderParams);
}
@@ -85,11 +85,8 @@ public class DependencySetup
EDhApiRenderApi renderingApiEnum = Config.Client.Advanced.Graphics.Experimental.renderingApi.get();
if (renderingApiEnum == EDhApiRenderApi.AUTO)
{
#if MC_VER < MC_1_21_11
renderingApiEnum = EDhApiRenderApi.OPEN_GL;
#else
renderingApiEnum = EDhApiRenderApi.BLAZE_3D;
#endif
IVersionConstants versionConstants = SingletonInjector.INSTANCE.get(IVersionConstants.class);
renderingApiEnum = versionConstants.getDefaultRenderingApi();
}
LOGGER.info("Setting DH Rendering API to: ["+renderingApiEnum+"].");
@@ -490,7 +490,11 @@ public class ClassicConfigGUI
// move forward or backwards depending on if the shift key is pressed
int index = shiftPressed ? startingIndex-1 : startingIndex+1;
index = (index >= enumList.size()) ? 0 : index;
// wrap around to the other side of the array when necessary
if (index >= enumList.size()) { index = 0; }
else if (index < 0) { index = enumList.size() - 1; }
// walk through the enums to find the next selectable one
while (index != startingIndex)
@@ -507,14 +511,8 @@ public class ClassicConfigGUI
index = shiftPressed ? index-1 : index+1;
// wrap around to the other side of the array when necessary
if (index >= enumList.size())
{
index = 0;
}
else if (index < 0)
{
index = enumList.size() - 1;
}
if (index >= enumList.size()) { index = 0; }
else if (index < 0) { index = enumList.size() - 1; }
}
@@ -239,7 +239,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
#else
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("MinecraftClientWrapper sendChatMessage", () ->
{
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
});
@@ -750,11 +750,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
{
updateManager.addPosToIgnore(chunkWrapper.getChunkPos());
}
else
{
// shouldn't happen, but just in case
LOGGER.warn("Unable to find chunk update manager for server level ["+BatchGenerationEnvironment.this.dhServerLevel+"], chunk updates may fail.");
}
}
}, MS_TO_IGNORE_CHUNK_AFTER_COMPLETION);
}
@@ -405,11 +405,6 @@ public class InternalServerGenerator
{
updateManager.addPosToIgnore(new DhChunkPos(chunkPos.x, chunkPos.z));
}
else
{
// shouldn't happen, but just in case
LOGGER.warn("Unable to find chunk update manager for server level ["+dhLevel+"], chunk updates may fail.");
}
}
}, MS_TO_IGNORE_CHUNK_AFTER_COMPLETION);