Changes for blaze/gl rendering config

This commit is contained in:
James Seibel
2026-03-10 11:40:36 -05:00
parent 559bad5676
commit 1b0f93db07
17 changed files with 535 additions and 67 deletions
+6 -4
View File
@@ -28,15 +28,17 @@ dependencies { // All of these dependencies are in Vanilla Minecraft, but we nee
implementation "org.lwjgl:lwjgl"
implementation "org.lwjgl:lwjgl-assimp"
implementation "org.lwjgl:lwjgl-glfw"
implementation "org.lwjgl:lwjgl-openal"
implementation "org.lwjgl:lwjgl-opengl"
// OpenGL is removed since DH now handles rendering in the "Common" project
// so we can use OpenGL for old MC versions and Blaze3D (IE Vulkan) for newer ones
// implementation "org.lwjgl:lwjgl-openal"
// implementation "org.lwjgl:lwjgl-opengl"
implementation "org.lwjgl:lwjgl-stb"
implementation "org.lwjgl:lwjgl-tinyfd"
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
// runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
// runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-tinyfd::$lwjglNatives"
@@ -40,6 +40,7 @@ import com.seibel.distanthorizons.core.util.objects.Pair;
import com.seibel.distanthorizons.core.util.objects.RollingAverage;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTerrainRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhVanillaFadeRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTestTriangleRenderer;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
@@ -595,7 +596,7 @@ public class ClientApi
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, renderParams);
if (!renderingCancelled)
{
BlazeLodRenderer.INSTANCE.render(renderParams, profiler);
LodRenderer.INSTANCE.render(renderParams, profiler);
}
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
@@ -608,7 +609,7 @@ public class ClientApi
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, renderParams);
if (!renderingCancelled)
{
BlazeLodRenderer.INSTANCE.renderDeferred(renderParams, profiler);
LodRenderer.INSTANCE.renderDeferred(renderParams, profiler);
}
@@ -620,14 +621,23 @@ public class ClientApi
}
else
{
IDhTestTriangleRenderer testRenderer = SingletonInjector.INSTANCE.get(IDhTestTriangleRenderer.class);
if (testRenderer != null)
if (!renderingDeferredLayer)
{
testRenderer.render();
}
else
{
RATE_LIMITED_LOGGER.warn("Unable to find singleton ["+ IDhTestTriangleRenderer.class.getSimpleName()+"]");
IDhTerrainRenderer lodRenderer = SingletonInjector.INSTANCE.get(IDhTerrainRenderer.class);
IDhTestTriangleRenderer testRenderer = SingletonInjector.INSTANCE.get(IDhTestTriangleRenderer.class);
if (testRenderer != null
&& lodRenderer != null)
{
lodRenderer.runRenderPassSetup(renderParams);
testRenderer.render();
lodRenderer.runRenderPassCleanup(renderParams);
}
else
{
RATE_LIMITED_LOGGER.warn("Unable to find singleton [" + IDhTestTriangleRenderer.class.getSimpleName() + "]");
}
}
}
}
@@ -835,8 +835,9 @@ public class Config
public static ConfigEntry<EDhApiRenderApi> renderingApi = new ConfigEntry.Builder<EDhApiRenderApi>()
.set(EDhApiRenderApi.AUTO)
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) // can't be changed while the game is running
.comment(""
+ "Requires a restart to change. \n"
+ " \n"
+ "Options: \n"
+ EDhApiRenderApi.AUTO + " \n"
+ EDhApiRenderApi.OPEN_GL + " \n"
@@ -215,11 +215,9 @@ public class LodBufferContainer implements AutoCloseable
}
IVertexBufferWrapper vbo = vbos[vboIndex];
IDhTerrainRenderer lodRenderer = SingletonInjector.INSTANCE.get(IDhTerrainRenderer.class);
ByteBuffer buffer = byteBuffers.get(i);
int size = buffer.limit() - buffer.position();
int vertexCount = size / lodRenderer.getVertexByteSize();
int vertexCount = size / LodQuadBuilder.BYTES_PER_VERTEX;
try
{
@@ -57,7 +57,8 @@ public class LodQuadBuilder
private final EDhApiDebugRendering debugRenderingMode;
private final EDhApiGrassSideRendering grassSideRenderingMode;
/** the number of bytes for */
public static final int BYTES_PER_VERTEX = 14;
public static final int[][][] DIRECTION_VERTEX_IBO_QUAD = new int[][][]
///region
@@ -117,6 +118,7 @@ public class LodQuadBuilder
//=============//
// constructor //
//=============//
//region
public LodQuadBuilder(boolean doTransparency, IClientLevelWrapper clientLevelWrapper)
{
@@ -134,6 +136,8 @@ public class LodQuadBuilder
}
//endregion
//===========//
@@ -482,6 +486,11 @@ public class LodQuadBuilder
}
private static int maxBufferByteSize = -1;
/**
* The max number of bytes we allow for a single Vertex buffer.
* If an LOD has more data than this it will be split
* up into multiple buffers.
*/
public static int getMaxBufferByteSize()
{
if (maxBufferByteSize != -1)
@@ -489,11 +498,9 @@ public class LodQuadBuilder
return maxBufferByteSize;
}
IDhTerrainRenderer LOD_RENDERER = SingletonInjector.INSTANCE.get(IDhTerrainRenderer.class);
/** number of bytes a single quad takes */
int QUADS_BYTE_SIZE = LOD_RENDERER.getVertexByteSize() * 4;
/** how big a single VBO can be in bytes */
// number of bytes a single quad takes
int QUADS_BYTE_SIZE = BYTES_PER_VERTEX * 4;
// how big a single VBO can be in bytes
int MAX_VBO_BYTE_SIZE = 10 * 1024 * 1024; // 10 MB
int MAX_QUADS_PER_BUFFER = MAX_VBO_BYTE_SIZE / QUADS_BYTE_SIZE;
int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE;
@@ -35,6 +35,7 @@ import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.coreapi.util.StringUtil;
@@ -83,6 +84,7 @@ public class F3Screen
{
String r = MinecraftTextFormat.RED;
String y = MinecraftTextFormat.YELLOW;
String a = MinecraftTextFormat.AQUA;
String cf = MinecraftTextFormat.CLEAR_FORMATTING;
@@ -123,6 +125,9 @@ public class F3Screen
int posX = DhSectionPos.getX(sectionPos);
int posZ = DhSectionPos.getZ(sectionPos);
messageList.add("LOD Pos: "+y+detailLevel+"*"+posX+","+posZ+cf);
AbstractDhRenderApiDefinition renderApiDef = SingletonInjector.INSTANCE.get(AbstractDhRenderApiDefinition.class);
messageList.add("Rendering API: "+a+renderApiDef.getApiName()+cf);
}
messageList.add("");
}
@@ -85,13 +85,13 @@ public class DhApiRenderProxy implements IDhApiRenderProxy
@Override
public DhApiResult<Integer> getDhDepthTextureId()
{
int activeTexture = BlazeLodRenderer.INSTANCE.getActiveDepthTextureId();
int activeTexture = -1;//DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId();
return (activeTexture == -1) ? DhApiResult.createFail("DH's depth texture hasn't been created and/or bound yet.", -1) : DhApiResult.createSuccess(activeTexture);
}
@Override
public DhApiResult<Integer> getDhColorTextureId()
{
int activeTexture = BlazeLodRenderer.INSTANCE.getActiveColorTextureId();
int activeTexture = -1;//DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveColorTextureId();
return (activeTexture == -1) ? DhApiResult.createFail("DH's color texture hasn't been created and/or bound yet.", -1) : DhApiResult.createSuccess(activeTexture);
}
@@ -33,7 +33,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.render.QuadTree.LodQuadTree;
import com.seibel.distanthorizons.core.render.QuadTree.LodRenderSection;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.DhFrustumBounds;
import com.seibel.distanthorizons.core.render.renderer.cullingFrustum.NeverCullFrustum;
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
@@ -48,7 +48,7 @@ import org.joml.Matrix4fc;
import java.util.ArrayList;
/**
* This object tells the {@link BlazeLodRenderer} what buffers to render
* This object tells the {@link LodRenderer} what buffers to render
*/
public class RenderBufferHandler implements AutoCloseable
{
@@ -45,7 +45,7 @@ public class RenderParams extends DhApiRenderParam
/** @see DhRenderState#vanillaFogEnabled */
public boolean vanillaFogEnabled;
public boolean validationRun = false;
public boolean hasBeenValidated = false;
@@ -120,7 +120,7 @@ public class RenderParams extends DhApiRenderParam
{
// Note: all strings here should be constants to prevent String allocations
this.validationRun = true;
this.hasBeenValidated = true;
if (!MC_CLIENT.playerExists())
@@ -104,7 +104,7 @@ public class RenderThreadTaskHandler
{
runnable.run();
// only try running for 4ms (240 FPS) at a time to prevent random lag spikes
// only try running for a limited amount of time to prevent lag spikes
long currentTimeMs = System.currentTimeMillis();
long runDuration = currentTimeMs - startTimeMs;
if (runDuration > msMaxRunTime)
@@ -0,0 +1,75 @@
/*
* 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.core.render.renderer;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.DhLogger;
import java.util.List;
import java.util.*;
/**
* Handles creating {@link DhApiRenderableBox}.
*
* @see IDhApiCustomRenderRegister
* @see DhApiRenderableBox
*/
public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFactory
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
public static final GenericRenderObjectFactory INSTANCE = new GenericRenderObjectFactory();
//=============//
// constructor //
//=============//
private GenericRenderObjectFactory() { }
//================//
// group creation //
//================//
@Override
public IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox box)
{
ArrayList<DhApiRenderableBox> list = new ArrayList<>();
list.add(box);
return this.createAbsolutePositionedGroup(resourceLocation, list);
}
@Override
public IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList)
{ return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); }
@Override
public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List<DhApiRenderableBox> boxList)
{ return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(0, 0, 0), boxList, false); }
}
@@ -39,7 +39,7 @@ import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
* This is where all the magic happens. <br>
* This is where LODs are draw to the world.
*/
public class BlazeLodRenderer
public class LodRenderer
{
public static final DhLogger LOGGER = new DhLoggerBuilder()
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
@@ -52,19 +52,22 @@ public class BlazeLodRenderer
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public static final BlazeLodRenderer INSTANCE = new BlazeLodRenderer();
public static final LodRenderer INSTANCE = new LodRenderer();
private boolean renderObjectsCreated = false;
private boolean vanillaSettingsOverridden = false;
//=============//
// constructor //
//=============//
//region
private BlazeLodRenderer() { }
private LodRenderer() { }
//endregion
@@ -105,7 +108,7 @@ public class BlazeLodRenderer
boolean firstPass = !runningDeferredPass;
// RenderParams parameter validation should be done before this
if (!renderParams.validationRun)
if (!renderParams.hasBeenValidated)
{
throw new IllegalArgumentException("Render parameters validation");
}
@@ -113,6 +116,11 @@ public class BlazeLodRenderer
RenderBufferHandler renderBufferHandler = renderParams.renderBufferHandler;
IDhGenericRenderer genericRenderer = renderParams.genericRenderer;
IDhTerrainRenderer lodRenderer = SingletonInjector.INSTANCE.get(IDhTerrainRenderer.class);
IDhSsaoRenderer ssaoRenderer = SingletonInjector.INSTANCE.get(IDhSsaoRenderer.class);
IDhFogRenderer fogRenderer = SingletonInjector.INSTANCE.get(IDhFogRenderer.class);
IDhFarFadeRenderer farFadeRenderer = SingletonInjector.INSTANCE.get(IDhFarFadeRenderer.class);
AbstractDebugWireframeRenderer debugWireframeRenderer = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
//=================//
@@ -122,7 +130,9 @@ public class BlazeLodRenderer
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderSetupEvent.class, renderParams);
profiler.push("LOD GL setup");
if (!this.renderObjectsCreated)
lodRenderer.runRenderPassSetup(renderParams);
if (!this.vanillaSettingsOverridden)
{
// only do this once, that way they can still be reverted if desired
if (Config.Client.Advanced.Graphics.overrideVanillaGraphicsSettings.get())
@@ -134,7 +144,7 @@ public class BlazeLodRenderer
MC.disableFabulousTransparency();
}
this.renderObjectsCreated = true;
this.vanillaSettingsOverridden = true;
}
if (firstPass)
@@ -144,12 +154,6 @@ public class BlazeLodRenderer
renderBufferHandler.buildRenderList(renderParams);
}
IDhTerrainRenderer lodRenderer = SingletonInjector.INSTANCE.get(IDhTerrainRenderer.class);
IDhSsaoRenderer ssaoRenderer = SingletonInjector.INSTANCE.get(IDhSsaoRenderer.class);
IDhFogRenderer fogRenderer = SingletonInjector.INSTANCE.get(IDhFogRenderer.class);
IDhFarFadeRenderer farFadeRenderer = SingletonInjector.INSTANCE.get(IDhFarFadeRenderer.class);
AbstractDebugWireframeRenderer debugWireframeRenderer = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
//===========//
@@ -274,6 +278,8 @@ public class BlazeLodRenderer
profiler.popPush("LOD cleanup");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams);
lodRenderer.runRenderPassCleanup(renderParams);
// end of internal LOD profiling
@@ -310,22 +316,4 @@ public class BlazeLodRenderer
//===============//
// API functions //
//===============//
//region
/** @return -1 if no frame buffer has been bound yet */
public int getActiveFramebufferId() { return -1; }
/** @return -1 if no texture has been bound yet */
public int getActiveColorTextureId() { return -1; }
/** @return -1 if no texture has been bound yet */
public int getActiveDepthTextureId() { return -1; }
//endregion
}
@@ -0,0 +1,361 @@
package com.seibel.distanthorizons.core.render.renderer;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
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.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
import org.jetbrains.annotations.Nullable;
import java.io.Closeable;
import java.util.*;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class RenderableBoxGroup
extends AbstractList<DhApiRenderableBox>
implements IDhApiRenderableBoxGroup, Closeable
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IWrapperFactory WRAPPER_FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
public static final AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0);
public final long id;
public final String resourceLocationNamespace;
public final String resourceLocationPath;
/** If false the boxes will be positioned relative to the level's origin */
public final boolean positionBoxesRelativeToGroupOrigin;
private final List<DhApiRenderableBox> boxList;
/** backup list which allows for uploading the boxes even it the main list is being modified on a different thread. */
private final List<DhApiRenderableBox> uploadBoxList;
private final DhApiVec3d originBlockPos;
public boolean active = true;
public boolean ssaoEnabled = true;
private boolean vertexDataDirty = true;
public byte skyLight = LodUtil.MAX_MC_LIGHT;
public byte blockLight = LodUtil.MIN_MC_LIGHT;
public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded();
@Nullable
public Consumer<DhApiRenderParam> beforeRenderFunc;
public Consumer<DhApiRenderParam> afterRenderFunc;
// instance data
public IDhGenericObjectVertexBufferContainer vertexBufferContainer = WRAPPER_FACTORY.createGenericObjectVboContainer();
/** double buffering for thread safety and to prevent locking the render thread during update */
private IDhGenericObjectVertexBufferContainer altVertexBufferContainer = WRAPPER_FACTORY.createGenericObjectVboContainer();
//=================//
// getters/setters //
//=================//
//region
@Override
public long getId() { return this.id; }
@Override
public String getResourceLocationNamespace() { return this.resourceLocationNamespace; }
@Override
public String getResourceLocationPath() { return this.resourceLocationPath; }
@Override
public void setOriginBlockPos(DhApiVec3d pos)
{
this.originBlockPos.x = pos.x;
this.originBlockPos.y = pos.y;
this.originBlockPos.z = pos.z;
}
@Override
public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); }
@Override
public void setSkyLight(int skyLight)
{
if (skyLight < LodUtil.MIN_MC_LIGHT
|| skyLight > LodUtil.MAX_MC_LIGHT)
{
throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
}
this.skyLight = (byte)skyLight;
}
@Override
public int getSkyLight() { return this.skyLight; }
@Override
public void setBlockLight(int blockLight)
{
if (blockLight < LodUtil.MIN_MC_LIGHT
|| blockLight > LodUtil.MAX_MC_LIGHT)
{
throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
}
this.blockLight = (byte)blockLight;
}
@Override
public int getBlockLight() { return this.blockLight; }
@Override
public void setPreRenderFunc(Consumer<DhApiRenderParam> func) { this.beforeRenderFunc = func; }
@Override
public void setPostRenderFunc(Consumer<DhApiRenderParam> func) { this.afterRenderFunc = func; }
@Override
public void setActive(boolean active) { this.active = active; }
@Override
public boolean isActive() { return this.active; }
@Override
public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; }
@Override
public boolean isSsaoEnabled() { return this.ssaoEnabled; }
@Override
public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; }
@Override
public DhApiRenderableBoxGroupShading getShading() { return this.shading; }
//endregion
//=============//
// constructor //
//=============//
//region
public RenderableBoxGroup(
String resourceLocation,
DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList,
boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException
{
String[] splitResourceLocation = resourceLocation.split(":");
if (splitResourceLocation.length != 2)
{
throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons.");
}
this.resourceLocationNamespace = splitResourceLocation[0];
this.resourceLocationPath = splitResourceLocation[1];
this.id = NEXT_ID_ATOMIC_INT.getAndIncrement();
this.boxList = Collections.synchronizedList(new ArrayList<>(boxList));
this.uploadBoxList = Collections.synchronizedList(new ArrayList<>(boxList));
this.originBlockPos = originBlockPos;
this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin;
}
//endregion
//=================//
// render building //
//=================//
//region
@Override
public void triggerBoxChange() { this.vertexDataDirty = true; }
/**
* Does nothing if the vertex data is already up-to-date
* and is meaningless if using direct rendering.
*/
public void tryUpdateInstancedDataAsync()
{
// if the alt container is done, swap it in
if (this.altVertexBufferContainer.getState() == IDhGenericObjectVertexBufferContainer.EState.READY_TO_UPLOAD)
{
this.altVertexBufferContainer.uploadDataToGpu();
// swap VBO references for rendering
IDhGenericObjectVertexBufferContainer temp = this.vertexBufferContainer;
this.vertexBufferContainer = this.altVertexBufferContainer;
this.altVertexBufferContainer = temp;
this.vertexDataDirty = false;
return;
}
// if the vertex data is already up to date, do nothing
if (!this.vertexDataDirty)
{
return;
}
PriorityTaskPicker.Executor executor = ThreadPoolUtil.getRenderLoadingExecutor();
if (executor == null || executor.isTerminated())
{
return;
}
// if the alternate container is already updating, don't double-queue it
if (this.altVertexBufferContainer.getState() == IDhGenericObjectVertexBufferContainer.EState.UPDATING_DATA)
{
return;
}
this.altVertexBufferContainer.setState(IDhGenericObjectVertexBufferContainer.EState.UPDATING_DATA);
//this.altInstancedVbos.tryRunRenderThreadSetup();
// copy over the box list so we can upload without concurrent modification issues
this.uploadBoxList.clear();
synchronized (this.uploadBoxList)
{
this.uploadBoxList.addAll(this.boxList);
}
try
{
executor.runTask(() ->
{
try
{
this.altVertexBufferContainer.updateVertexData(this.uploadBoxList);
}
catch (Exception e)
{
LOGGER.error("Unexpected error updating instanced VBO data for: ["+this+"], error: ["+e.getMessage()+"].", e);
this.altVertexBufferContainer.setState(IDhGenericObjectVertexBufferContainer.EState.ERROR);
}
});
}
catch (RejectedExecutionException ignore)
{
// the executor was shut down, it should be back up shortly and able to accept new jobs
this.altVertexBufferContainer.setState(IDhGenericObjectVertexBufferContainer.EState.NEW);
}
}
//endregion
//===============//
// render events //
//===============//
//region
/**
* This is called before every frame, even if {@link this#isActive()} returns false. <br>
* {@link this#isActive()} can be changed at this point before the object is rendered to the frame.
*/
public void preRender(DhApiRenderParam renderEventParam)
{
if (this.beforeRenderFunc != null)
{
this.beforeRenderFunc.accept(renderEventParam);
}
}
/**
* Called after rendering is completed. <br>
* Can be used to handle any necessary cleanup.
*/
public void postRender(DhApiRenderParam renderEventParam)
{
if (this.afterRenderFunc != null)
{
this.afterRenderFunc.accept(renderEventParam);
}
}
//endregion
//================//
// List Overrides //
//================//
//region
@Override
public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); }
@Override
public DhApiRenderableBox get(int index) { return this.boxList.get(index); }
@Override
public int size() { return this.boxList.size(); }
@Override
public boolean removeIf(Predicate<? super DhApiRenderableBox> filter) { return this.boxList.removeIf(filter); }
@Override
public boolean remove(Object obj) { return this.boxList.remove(obj); }
@Override
public DhApiRenderableBox remove(int index) { return this.boxList.remove(index); }
@Override
public void replaceAll(UnaryOperator<DhApiRenderableBox> operator) { this.boxList.replaceAll(operator); }
@Override
public void sort(Comparator<? super DhApiRenderableBox> comparator) { this.boxList.sort(comparator); }
@Override
public void forEach(Consumer<? super DhApiRenderableBox> action) { this.boxList.forEach(action); }
@Override
public Spliterator<DhApiRenderableBox> spliterator() { return this.boxList.spliterator(); }
@Override
public Stream<DhApiRenderableBox> stream() { return this.boxList.stream(); }
@Override
public Stream<DhApiRenderableBox> parallelStream() { return this.boxList.parallelStream(); }
@Override
public void clear() { this.boxList.clear(); }
//endregion
//================//
// base overrides //
//================//
//region
@Override
public String toString() { return "["+this.resourceLocationNamespace+":"+this.resourceLocationPath+"] ID:["+this.id+"], pos:[("+this.originBlockPos.x+", "+this.originBlockPos.y+", "+this.originBlockPos.z+")], size:["+this.size()+"], active:["+this.active+"]"; }
@Override
public void close()
{
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
{
this.vertexBufferContainer.close();
this.altVertexBufferContainer.close();
});
}
//endregion
}
@@ -10,6 +10,18 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab
public abstract class AbstractDhRenderApiDefinition implements IBindable
{
//=========//
// getters //
//=========//
//region
/** Used for debugging */
public abstract String getApiName();
//endregion
//============//
// singletons //
//============//
@@ -32,10 +32,10 @@ public interface IDhTerrainRenderer extends IBindable
SortedArraySet<LodBufferContainer> bufferContainers,
IProfilerWrapper profiler);
@Deprecated // TODO put somewhere else
int getVertexByteSize();
// TODO should these go somewhere else?
void runRenderPassSetup(RenderParams renderParams);
void runRenderPassCleanup(RenderParams renderParams);
void applyToMcTexture();
void clearDepth();
void clearColor();
@@ -418,7 +418,7 @@
"distanthorizons.config.client.advanced.graphics.experimental.renderingApi":
"Rendering API",
"distanthorizons.config.client.advanced.graphics.experimental.renderingApi.@tooltip":
"",
"Requires a restart to change.",
@@ -1044,7 +1044,7 @@
"distanthorizons.config.enum.EDhApiRendererMode.DEFAULT":
"Default",
"distanthorizons.config.enum.EDhApiRendererMode.DEBUG":
"Debug",
"Debug Triangle",
"distanthorizons.config.enum.EDhApiRendererMode.DISABLED":
"Disabled",
@@ -1121,6 +1121,15 @@
"distanthorizons.config.enum.EDhApiGrassSideRendering.FADE_TO_DIRT":
"Fade To Dirt",
"distanthorizons.config.enum.EDhApiGrassSideRendering.AS_DIRT":
"As Dirt"
"As Dirt",
"distanthorizons.config.enum.EDhApiRenderApi.AUTO":
"Auto",
"distanthorizons.config.enum.EDhApiRenderApi.OPEN_GL":
"OpenGL",
"distanthorizons.config.enum.EDhApiRenderApi.BLAZE_3D":
"Blaze3D"
}
@@ -68,7 +68,7 @@ void main()
uint lights = meta & 0xFFu;
float skyLight = (float(lights/16u)+0.5) / 16.0;
float blockLight = (mod(float(lights), 16.0)+0.5) / 16.0;
vertexColor = vec4(1.0); //vec4(texture(uLightMap, vec2(skyLight, blockLight)).xyz, 1.0);
vertexColor = vec4(texture(uLightMap, vec2(skyLight, blockLight)).xyz, 1.0);
if (!uIsWhiteWorld)
{