Merge branch 'blazeRender'
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package com.seibel.distanthorizons.api.enums.config;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
|
||||
/**
|
||||
* AUTO, <br>
|
||||
* OPEN_GL, <br>
|
||||
* BLAZE_3D, <br><br>
|
||||
*
|
||||
* @since API 6.0.0
|
||||
* @version 2026-3-10
|
||||
*/
|
||||
public enum EDhApiRenderApi
|
||||
{
|
||||
AUTO,
|
||||
OPEN_GL,
|
||||
BLAZE_3D;
|
||||
|
||||
}
|
||||
+2
-1
@@ -3,6 +3,7 @@ package com.seibel.distanthorizons.api.interfaces.render;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,7 +19,7 @@ import java.util.List;
|
||||
* @version 2024-7-3
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiCustomRenderObjectFactory
|
||||
public interface IDhApiCustomRenderObjectFactory extends IBindable
|
||||
{
|
||||
/**
|
||||
* Creates a {@link IDhApiRenderableBoxGroup} from for the given {@link DhApiRenderableBox}
|
||||
|
||||
+6
@@ -60,6 +60,8 @@ public class DhApiRenderParam implements IDhApiEventParam
|
||||
public final DhApiMat4f dhProjectionMatrix;
|
||||
/** The model view matrix Distant Horizons is using to render this frame. */
|
||||
public final DhApiMat4f dhModelViewMatrix;
|
||||
/** combination of the MVM and projection matrices */
|
||||
public final DhApiMat4f dhMvmProjMatrix;
|
||||
|
||||
public final int worldYOffset;
|
||||
|
||||
@@ -111,6 +113,10 @@ public class DhApiRenderParam implements IDhApiEventParam
|
||||
this.dhProjectionMatrix = newDhProjectionMatrix;
|
||||
this.dhModelViewMatrix = newDhModelViewMatrix;
|
||||
|
||||
DhApiMat4f combinedMatrix = new DhApiMat4f(this.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(this.dhModelViewMatrix);
|
||||
this.dhMvmProjMatrix = combinedMatrix;
|
||||
|
||||
this.worldYOffset = worldYOffset;
|
||||
this.clientLevelWrapper = clientLevelWrapper;
|
||||
|
||||
|
||||
+5
@@ -74,6 +74,11 @@ public class DependencyInjector<BindableType extends IBindable> implements IDepe
|
||||
throw new IllegalStateException("The dependency [" + dependencyInterface.getSimpleName() + "] has already been bound.");
|
||||
}
|
||||
|
||||
if (dependencyImplementation == null)
|
||||
{
|
||||
throw new NullPointerException("Can't bind null to ["+dependencyInterface.getSimpleName()+"]");
|
||||
}
|
||||
|
||||
|
||||
// make sure the given dependency implements the necessary interfaces
|
||||
boolean implementsInterface = this.checkIfClassImplements(dependencyImplementation.getClass(), dependencyInterface) ||
|
||||
|
||||
+6
-4
@@ -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"
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.seibel.distanthorizons.core;
|
||||
|
||||
import com.github.luben.zstd.ZstdOutputStream;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderEvent;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
@@ -27,7 +28,6 @@ import com.seibel.distanthorizons.core.config.eventHandlers.IgnoredDimensionCsvH
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.core.sql.DatabaseUpdater;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.world.DhApiWorldProxy;
|
||||
@@ -36,7 +36,6 @@ import com.seibel.distanthorizons.core.api.external.methods.data.DhApiTerrainDat
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||
import net.jpountz.lz4.LZ4FrameOutputStream;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.sqlite.SQLiteJDBCLoader;
|
||||
@@ -162,13 +161,17 @@ public class Initializer
|
||||
DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE;
|
||||
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
|
||||
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
|
||||
DhApi.Delayed.customRenderObjectFactory = GenericRenderObjectFactory.INSTANCE;
|
||||
DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
if (DhApi.Delayed.wrapperFactory == null)
|
||||
{
|
||||
LOGGER.error("Programmer Error: No ["+IWrapperFactory.class.getSimpleName()+"] assigned to the DhApi.");
|
||||
MC_CLIENT.crashMinecraft("Programmer Error: No ["+IWrapperFactory.class.getSimpleName()+"] assigned to the DhApi.", new Exception());
|
||||
}
|
||||
|
||||
DhApi.Delayed.customRenderObjectFactory = SingletonInjector.INSTANCE.get(IDhApiCustomRenderObjectFactory.class);
|
||||
if (DhApi.Delayed.customRenderObjectFactory == null)
|
||||
{
|
||||
MC_CLIENT.crashMinecraft("Programmer Error: No ["+IDhApiCustomRenderObjectFactory.class.getSimpleName()+"] assigned to the DhApi.", new Exception());
|
||||
}
|
||||
|
||||
DhApi.events.bind(DhApiBeforeRenderEvent.class, IgnoredDimensionCsvHandler.INSTANCE);
|
||||
|
||||
|
||||
+6
-4
@@ -34,7 +34,7 @@ import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.util.DhApiTerrainDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
@@ -66,6 +66,8 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
// debugging values
|
||||
private static volatile boolean debugThreadRunning = false;
|
||||
private static DhApiTerrainDataCache debugDataCache = new DhApiTerrainDataCache();
|
||||
@@ -588,9 +590,9 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
if (rayCast.success
|
||||
&& rayCast.payload != null)
|
||||
{
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(
|
||||
DEBUG_RENDERER.makeParticle(
|
||||
new AbstractDebugWireframeRenderer.BoxParticle(
|
||||
new AbstractDebugWireframeRenderer.Box(
|
||||
DhSectionPos.encode((byte) 0, rayCast.payload.pos.x, rayCast.payload.pos.z),
|
||||
rayCast.payload.dataPoint.bottomYBlockPos,
|
||||
rayCast.payload.dataPoint.topYBlockPos,
|
||||
|
||||
@@ -31,6 +31,8 @@ import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.*;
|
||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
@@ -38,6 +40,10 @@ 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.IDhMetaRenderer;
|
||||
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;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
@@ -47,7 +53,6 @@ import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.core.world.DhClientWorld;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
@@ -73,6 +78,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
||||
public class ClientApi
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder().maxCountPerSecond(1).build();
|
||||
|
||||
public static final ClientApi INSTANCE = new ClientApi();
|
||||
|
||||
@@ -414,11 +420,26 @@ public class ClientApi
|
||||
private void renderLodLayer(boolean renderingDeferredLayer)
|
||||
{
|
||||
IProfilerWrapper profiler = MC_CLIENT.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("DH-RenderLevel");
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// debugging //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
//DhApiTerrainDataRepo.asyncDebugMethod(
|
||||
// RENDER_STATE.clientLevelWrapper,
|
||||
// MC_CLIENT.getPlayerBlockPos().getX(),
|
||||
// MC_CLIENT.getPlayerBlockPos().getY(),
|
||||
// MC_CLIENT.getPlayerBlockPos().getZ()
|
||||
//);
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// render thread tasks //
|
||||
//=====================//
|
||||
@@ -445,11 +466,8 @@ public class ClientApi
|
||||
|
||||
try
|
||||
{
|
||||
// make sure the GLProxy is created for future use
|
||||
GLProxy glProxy = GLProxy.getInstance();
|
||||
|
||||
// these tasks always need to be called, regardless of whether the renderer is enabled or not to prevent memory leaks
|
||||
glProxy.runRenderThreadTasks();
|
||||
RenderThreadTaskHandler.INSTANCE.runRenderThreadTasks();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -487,6 +505,7 @@ public class ClientApi
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// parameter setup //
|
||||
//=================//
|
||||
@@ -571,32 +590,57 @@ public class ClientApi
|
||||
try
|
||||
{
|
||||
// render pass //
|
||||
|
||||
if (!renderingDeferredLayer)
|
||||
if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEFAULT)
|
||||
{
|
||||
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, renderParams);
|
||||
if (!renderingCancelled)
|
||||
if (!renderingDeferredLayer)
|
||||
{
|
||||
LodRenderer.INSTANCE.render(renderParams, profiler);
|
||||
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, renderParams);
|
||||
if (!renderingCancelled)
|
||||
{
|
||||
LodRenderer.INSTANCE.render(renderParams, profiler);
|
||||
}
|
||||
|
||||
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
|
||||
{
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
|
||||
else
|
||||
{
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
|
||||
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, renderParams);
|
||||
if (!renderingCancelled)
|
||||
{
|
||||
LodRenderer.INSTANCE.renderDeferred(renderParams, profiler);
|
||||
}
|
||||
|
||||
|
||||
if (DhApi.Delayed.renderProxy.getDeferTransparentRendering())
|
||||
{
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean renderingCancelled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDeferredRenderEvent.class, renderParams);
|
||||
if (!renderingCancelled)
|
||||
if (!renderingDeferredLayer)
|
||||
{
|
||||
LodRenderer.INSTANCE.renderDeferred(renderParams, profiler);
|
||||
}
|
||||
|
||||
|
||||
if (DhApi.Delayed.renderProxy.getDeferTransparentRendering())
|
||||
{
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
|
||||
IDhMetaRenderer metaRenderer = SingletonInjector.INSTANCE.get(IDhMetaRenderer.class);
|
||||
IDhTestTriangleRenderer testRenderer = SingletonInjector.INSTANCE.get(IDhTestTriangleRenderer.class);
|
||||
if (testRenderer != null
|
||||
&& metaRenderer != null)
|
||||
{
|
||||
// meta renderer needed for render state/texture
|
||||
// for setup on some APIs (IE openGL)
|
||||
metaRenderer.runRenderPassSetup(renderParams);
|
||||
|
||||
testRenderer.render(renderParams);
|
||||
|
||||
metaRenderer.runRenderPassCleanup(renderParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
RATE_LIMITED_LOGGER.warn("Unable to find singleton [" + IDhTestTriangleRenderer.class.getSimpleName() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -616,7 +660,6 @@ public class ClientApi
|
||||
|
||||
|
||||
profiler.pop(); // end LOD
|
||||
profiler.push("terrain"); // go back into "terrain"
|
||||
}
|
||||
|
||||
///endregion
|
||||
@@ -634,6 +677,12 @@ public class ClientApi
|
||||
*/
|
||||
public void renderFadeOpaque()
|
||||
{
|
||||
IDhVanillaFadeRenderer fadeRenderer = SingletonInjector.INSTANCE.get(IDhVanillaFadeRenderer.class);
|
||||
if (fadeRenderer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// only fade when DH is rendering
|
||||
if (Config.Client.Advanced.Debugging.rendererMode.get() != EDhApiRendererMode.DISABLED
|
||||
&&
|
||||
@@ -646,7 +695,8 @@ public class ClientApi
|
||||
// don't fade when Iris shaders are active, otherwise the rendering can get weird
|
||||
&& !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering())
|
||||
{
|
||||
VanillaFadeRenderer.INSTANCE.render(RENDER_STATE.mcModelViewMatrix, RENDER_STATE.mcProjectionMatrix, RENDER_STATE.partialTickTime, RENDER_STATE.clientLevelWrapper);
|
||||
RenderParams renderParams = new RenderParams(EDhApiRenderPass.OPAQUE, RENDER_STATE);
|
||||
fadeRenderer.render(renderParams);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -656,6 +706,12 @@ public class ClientApi
|
||||
*/
|
||||
public void renderFadeTransparent()
|
||||
{
|
||||
IDhVanillaFadeRenderer fadeRenderer = SingletonInjector.INSTANCE.get(IDhVanillaFadeRenderer.class);
|
||||
if (fadeRenderer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// only fade when DH is rendering
|
||||
if (Config.Client.Advanced.Debugging.rendererMode.get() != EDhApiRendererMode.DISABLED)
|
||||
{
|
||||
@@ -670,7 +726,8 @@ public class ClientApi
|
||||
&& !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
|
||||
if (renderFade)
|
||||
{
|
||||
VanillaFadeRenderer.INSTANCE.render(RENDER_STATE.mcModelViewMatrix, RENDER_STATE.mcProjectionMatrix, RENDER_STATE.partialTickTime, RENDER_STATE.clientLevelWrapper);
|
||||
RenderParams renderParams = new RenderParams(EDhApiRenderPass.TRANSPARENT, RENDER_STATE);
|
||||
fadeRenderer.render(renderParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.network.event.internal.CloseInternalEvent;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.LevelInitMessage;
|
||||
import com.seibel.distanthorizons.core.network.session.NetworkSession;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -90,7 +90,7 @@ public class ClientPluginChannelApi
|
||||
|
||||
LOGGER.info("Server level key received: [" + msg.levelKey + "].");
|
||||
|
||||
GLProxy.queueRunningOnRenderThread(() ->
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
IClientLevelWrapper clientLevel = MC.getWrappedClientLevel(true);
|
||||
IServerKeyedClientLevel existingKeyedClientLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
@@ -105,7 +105,10 @@ public class SharedApi
|
||||
else
|
||||
{
|
||||
ThreadPoolUtil.shutdownThreadPools();
|
||||
DebugRenderer.clearRenderables();
|
||||
|
||||
// delayed get because SharedApi will be created before the singleton has been bound
|
||||
AbstractDebugWireframeRenderer debugWireframeRenderer = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
debugWireframeRenderer.clearRenderables();
|
||||
|
||||
if (MC_RENDER != null)
|
||||
{
|
||||
|
||||
@@ -833,6 +833,20 @@ public class Config
|
||||
.addListener(IgnoredDimensionCsvHandler.INSTANCE)
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<EDhApiRenderApi> renderingApi = new ConfigEntry.Builder<EDhApiRenderApi>()
|
||||
.set(EDhApiRenderApi.AUTO)
|
||||
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) // very experimental option and only supported
|
||||
.comment(""
|
||||
+ "Requires a restart to change. \n"
|
||||
+ " \n"
|
||||
+ "Options: \n"
|
||||
+ EDhApiRenderApi.AUTO + " - changes based on the most likely API for that MC version \n"
|
||||
+ EDhApiRenderApi.OPEN_GL + " - Default \n"
|
||||
+ EDhApiRenderApi.BLAZE_3D + " - Only supported on MC 1.21.11 \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* 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.config.gui;
|
||||
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.system.jawt.JAWT;
|
||||
import org.lwjgl.system.macosx.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
import static org.lwjgl.glfw.GLFWNativeCocoa.*;
|
||||
import static org.lwjgl.glfw.GLFWNativeWin32.*;
|
||||
import static org.lwjgl.glfw.GLFWNativeX11.*;
|
||||
import static org.lwjgl.system.JNI.*;
|
||||
import static org.lwjgl.system.jawt.JAWTFunctions.*;
|
||||
import static org.lwjgl.system.macosx.ObjCRuntime.*;
|
||||
|
||||
// Some of the code is from https://github.com/LWJGL/lwjgl3/blob/master/modules/samples/src/test/java/org/lwjgl/demo/system/jawt/EmbeddedFrameUtil.java
|
||||
// which is licensed under https://www.lwjgl.org/license
|
||||
|
||||
/**
|
||||
* Some utils for embedding awt and swing items into lwjgl windows
|
||||
*
|
||||
* @author Ran
|
||||
* @author coolGi
|
||||
*/
|
||||
public final class EmbeddedFrameUtil
|
||||
{
|
||||
|
||||
private static final int JAVA_VERSION;
|
||||
|
||||
private static final JAWT awt;
|
||||
|
||||
static
|
||||
{
|
||||
Pattern p = Pattern.compile("^(?:1[.])?([1-9][0-9]*)[.-]");
|
||||
Matcher m = p.matcher(System.getProperty("java.version"));
|
||||
|
||||
if (!m.find())
|
||||
{
|
||||
throw new IllegalStateException("Failed to parse java.version");
|
||||
}
|
||||
|
||||
JAVA_VERSION = Integer.parseInt(m.group(1));
|
||||
|
||||
awt = JAWT.calloc();
|
||||
awt.version(JAVA_VERSION < 9 ? JAWT_VERSION_1_4 : JAWT_VERSION_9);
|
||||
if (!JAWT_GetAWT(awt))
|
||||
{
|
||||
throw new RuntimeException("GetAWT failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getEmbeddedFrameImpl()
|
||||
{
|
||||
switch (EPlatform.get())
|
||||
{
|
||||
case LINUX:
|
||||
return "sun.awt.X11.XEmbeddedFrame";
|
||||
case WINDOWS:
|
||||
return "sun.awt.windows.WEmbeddedFrame";
|
||||
case MACOS:
|
||||
return "sun.lwawt.macosx.CViewEmbeddedFrame";
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private static long getEmbeddedFrameHandle(long window)
|
||||
{
|
||||
switch (EPlatform.get())
|
||||
{
|
||||
case LINUX:
|
||||
return glfwGetX11Window(window);
|
||||
case WINDOWS:
|
||||
return glfwGetWin32Window(window);
|
||||
case MACOS:
|
||||
long objc_msgSend = ObjCRuntime.getLibrary().getFunctionAddress("objc_msgSend");
|
||||
return invokePPP(glfwGetCocoaWindow(window), sel_getUid("contentView"), objc_msgSend);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public static Frame embeddedFrameCreate(long window)
|
||||
{
|
||||
if (JAVA_VERSION < 9)
|
||||
{
|
||||
try
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Frame> EmdeddedFrame = (Class<? extends Frame>) Class.forName(getEmbeddedFrameImpl());
|
||||
Constructor<? extends Frame> c = EmdeddedFrame.getConstructor(long.class);
|
||||
|
||||
return c.newInstance(getEmbeddedFrameHandle(window));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return nJAWT_CreateEmbeddedFrame(getEmbeddedFrameHandle(window), awt.CreateEmbeddedFrame());
|
||||
}
|
||||
}
|
||||
|
||||
static void embeddedFrameSynthesizeWindowActivation(Frame embeddedFrame, boolean doActivate)
|
||||
{
|
||||
if (JAVA_VERSION < 9)
|
||||
{
|
||||
try
|
||||
{
|
||||
embeddedFrame
|
||||
.getClass()
|
||||
.getMethod("synthesizeWindowActivation", boolean.class)
|
||||
.invoke(embeddedFrame, doActivate);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JAWT_SynthesizeWindowActivation(embeddedFrame, doActivate, awt.SynthesizeWindowActivation());
|
||||
}
|
||||
}
|
||||
|
||||
public static void embeddedFrameSetBounds(Frame embeddedFrame, int x, int y, int width, int height)
|
||||
{
|
||||
if (JAVA_VERSION < 9)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method setLocationPrivate = embeddedFrame
|
||||
.getClass()
|
||||
.getSuperclass()
|
||||
.getDeclaredMethod("setBoundsPrivate", int.class, int.class, int.class, int.class);
|
||||
setLocationPrivate.setAccessible(true);
|
||||
setLocationPrivate.invoke(embeddedFrame, x, y, width, height);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JAWT_SetBounds(embeddedFrame, x, y, width, height, awt.SetBounds());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void hideFrame(@NotNull Frame embeddedFrame)
|
||||
{
|
||||
embeddedFrame.setVisible(false);
|
||||
embeddedFrameSynthesizeWindowActivation(embeddedFrame, false);
|
||||
}
|
||||
|
||||
public static void showFrame(@NotNull Frame embeddedFrame)
|
||||
{
|
||||
embeddedFrameSynthesizeWindowActivation(embeddedFrame, true);
|
||||
embeddedFrame.setVisible(true);
|
||||
}
|
||||
public static void placeAtCenter(Frame embeddedFrame, int windowWidth, int windowHeight, int frameWidth, int frameHeight, float scale)
|
||||
{
|
||||
float scaleFactor = (100.0F - scale) / 100.0F;
|
||||
float newWidth = frameWidth * scaleFactor;
|
||||
float newHeight = frameHeight * scaleFactor;
|
||||
float newX = (windowWidth - newWidth) / 2F;
|
||||
float newY = (windowHeight - newHeight) / 2F;
|
||||
embeddedFrameSetBounds(embeddedFrame, Math.round(newX), Math.round(newY), Math.round(newWidth), Math.round(newHeight));
|
||||
}
|
||||
|
||||
}
|
||||
+55
-64
@@ -19,15 +19,17 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding;
|
||||
|
||||
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.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.StatsMap;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTerrainRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -44,12 +46,7 @@ public class LodBufferContainer implements AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
/** number of bytes a single quad takes */
|
||||
public static final int QUADS_BYTE_SIZE = LodUtil.DH_VERTEX_FORMAT.getByteSize() * 4;
|
||||
/** how big a single VBO can be in bytes */
|
||||
public static final int MAX_VBO_BYTE_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||
public static final int MAX_QUADS_PER_BUFFER = MAX_VBO_BYTE_SIZE / QUADS_BYTE_SIZE;
|
||||
public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE;
|
||||
private static final IWrapperFactory WRAPPER_FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
|
||||
|
||||
/** the position closest to minimum X/Z infinity and the level's lowest Y */
|
||||
@@ -58,8 +55,10 @@ public class LodBufferContainer implements AutoCloseable
|
||||
|
||||
public boolean buffersUploaded = false;
|
||||
|
||||
public GLVertexBuffer[] vbos;
|
||||
public GLVertexBuffer[] vbosTransparent;
|
||||
public IVertexBufferWrapper[] vbos;
|
||||
public IVertexBufferWrapper[] vbosTransparent;
|
||||
|
||||
public ILodContainerUniformBufferWrapper uniformContainer = WRAPPER_FACTORY.createLodContainerUniformWrapper();
|
||||
|
||||
private final AtomicReference<CompletableFuture<LodBufferContainer>> uploadFutureRef = new AtomicReference<>(null);
|
||||
|
||||
@@ -68,20 +67,26 @@ public class LodBufferContainer implements AutoCloseable
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
public LodBufferContainer(long pos, DhBlockPos minCornerBlockPos)
|
||||
{
|
||||
this.pos = pos;
|
||||
this.minCornerBlockPos = minCornerBlockPos;
|
||||
this.vbos = new GLVertexBuffer[0];
|
||||
this.vbosTransparent = new GLVertexBuffer[0];
|
||||
this.vbos = new IVertexBufferWrapper[0];
|
||||
this.vbosTransparent = new IVertexBufferWrapper[0];
|
||||
|
||||
this.uniformContainer.createUniformData(this);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// buffer uploading //
|
||||
//==================//
|
||||
//region
|
||||
|
||||
/** Should be run on a DH thread. */
|
||||
public synchronized CompletableFuture<LodBufferContainer> makeAndUploadBuffersAsync(LodQuadBuilder builder)
|
||||
@@ -119,12 +124,12 @@ public class LodBufferContainer implements AutoCloseable
|
||||
ArrayList<ByteBuffer> opaqueBuffers = builder.makeOpaqueVertexBuffers();
|
||||
ArrayList<ByteBuffer> transparentBuffers = builder.makeTransparentVertexBuffers();
|
||||
|
||||
this.vbos = resizeBuffer(this.vbos, opaqueBuffers.size());
|
||||
this.vbosTransparent = resizeBuffer(this.vbosTransparent, transparentBuffers.size());
|
||||
this.vbos = resizeBufferArray(this.vbos, opaqueBuffers.size());
|
||||
this.vbosTransparent = resizeBufferArray(this.vbosTransparent, transparentBuffers.size());
|
||||
|
||||
|
||||
// upload on MC's render thread
|
||||
GLProxy.queueRunningOnRenderThread(() ->
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -135,11 +140,9 @@ public class LodBufferContainer implements AutoCloseable
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
EDhApiGpuUploadMethod gpuUploadMethod = GLProxy.getInstance().getGpuUploadMethod();
|
||||
|
||||
// upload on the render thread
|
||||
uploadBuffersDirect(this.vbos, opaqueBuffers, gpuUploadMethod);
|
||||
uploadBuffersDirect(this.vbosTransparent, transparentBuffers, gpuUploadMethod);
|
||||
uploadBuffers(this.vbos, opaqueBuffers);
|
||||
uploadBuffers(this.vbosTransparent, transparentBuffers);
|
||||
this.buffersUploaded = true;
|
||||
|
||||
// success
|
||||
@@ -173,14 +176,14 @@ public class LodBufferContainer implements AutoCloseable
|
||||
|
||||
return future;
|
||||
}
|
||||
private static GLVertexBuffer[] resizeBuffer(GLVertexBuffer[] vbos, int newSize)
|
||||
private static IVertexBufferWrapper[] resizeBufferArray(IVertexBufferWrapper[] vbos, int newSize)
|
||||
{
|
||||
if (vbos.length == newSize)
|
||||
{
|
||||
return vbos;
|
||||
}
|
||||
|
||||
GLVertexBuffer[] newVbos = new GLVertexBuffer[newSize];
|
||||
IVertexBufferWrapper[] newVbos = new IVertexBufferWrapper[newSize];
|
||||
System.arraycopy(vbos, 0, newVbos, 0, Math.min(vbos.length, newSize));
|
||||
if (newSize < vbos.length)
|
||||
{
|
||||
@@ -194,9 +197,7 @@ public class LodBufferContainer implements AutoCloseable
|
||||
}
|
||||
return newVbos;
|
||||
}
|
||||
private static void uploadBuffersDirect(
|
||||
GLVertexBuffer[] vbos, ArrayList<ByteBuffer> byteBuffers,
|
||||
EDhApiGpuUploadMethod uploadMethod) throws InterruptedException
|
||||
private static void uploadBuffers(IVertexBufferWrapper[] vbos, ArrayList<ByteBuffer> byteBuffers) throws InterruptedException
|
||||
{
|
||||
int vboIndex = 0;
|
||||
for (int i = 0; i < byteBuffers.size(); i++)
|
||||
@@ -210,18 +211,17 @@ public class LodBufferContainer implements AutoCloseable
|
||||
// get or create the VBO
|
||||
if (vbos[vboIndex] == null)
|
||||
{
|
||||
vbos[vboIndex] = new GLVertexBuffer(uploadMethod.useBufferStorage);
|
||||
vbos[vboIndex] = SingletonInjector.INSTANCE.get(IWrapperFactory.class).createVboWrapper("distantHorizons:McLodRenderer");
|
||||
}
|
||||
GLVertexBuffer vbo = vbos[vboIndex];
|
||||
|
||||
IVertexBufferWrapper vbo = vbos[vboIndex];
|
||||
|
||||
ByteBuffer buffer = byteBuffers.get(i);
|
||||
int size = buffer.limit() - buffer.position();
|
||||
int vertexCount = size / LodQuadBuilder.BYTES_PER_VERTEX;
|
||||
|
||||
try
|
||||
{
|
||||
vbo.bind();
|
||||
vbo.uploadBuffer(buffer, size / LodUtil.DH_VERTEX_FORMAT.getByteSize(), uploadMethod, FULL_SIZED_BUFFER);
|
||||
vbo.upload(buffer, vertexCount);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -239,11 +239,14 @@ public class LodBufferContainer implements AutoCloseable
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
//region
|
||||
|
||||
/** can be used when debugging */
|
||||
public boolean hasNonNullVbos() { return this.vbos != null || this.vbosTransparent != null; }
|
||||
@@ -268,35 +271,14 @@ public class LodBufferContainer implements AutoCloseable
|
||||
|
||||
public boolean uploadInProgress() { return this.uploadFutureRef.get() != null; }
|
||||
|
||||
public void debugDumpStats(StatsMap statsMap)
|
||||
{
|
||||
statsMap.incStat("RenderBuffers");
|
||||
statsMap.incStat("SimpleRenderBuffers");
|
||||
for (GLVertexBuffer vertexBuffer : this.vbos)
|
||||
{
|
||||
if (vertexBuffer != null)
|
||||
{
|
||||
statsMap.incStat("VBOs");
|
||||
if (vertexBuffer.getSize() == FULL_SIZED_BUFFER)
|
||||
{
|
||||
statsMap.incStat("FullsizedVBOs");
|
||||
}
|
||||
|
||||
if (vertexBuffer.getSize() == 0)
|
||||
{
|
||||
GLProxy.LOGGER.warn("VBO with size 0");
|
||||
}
|
||||
statsMap.incBytesStat("TotalUsage", vertexBuffer.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
/**
|
||||
* This method is called when object is no longer in use.
|
||||
@@ -309,21 +291,30 @@ public class LodBufferContainer implements AutoCloseable
|
||||
{
|
||||
this.buffersUploaded = false;
|
||||
|
||||
for (GLVertexBuffer buffer : this.vbos)
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
if (buffer != null)
|
||||
for (IVertexBufferWrapper buffer : this.vbos)
|
||||
{
|
||||
buffer.destroyAsync();
|
||||
if (buffer != null)
|
||||
{
|
||||
buffer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (GLVertexBuffer buffer : this.vbosTransparent)
|
||||
{
|
||||
if (buffer != null)
|
||||
|
||||
for (IVertexBufferWrapper buffer : this.vbosTransparent)
|
||||
{
|
||||
buffer.destroyAsync();
|
||||
if (buffer != null)
|
||||
{
|
||||
buffer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.uniformContainer.close();
|
||||
});
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+26
-10
@@ -32,8 +32,8 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTerrainRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
@@ -306,7 +310,7 @@ public class LodQuadBuilder
|
||||
// create a new buffer
|
||||
if (buffer == null || !buffer.hasRemaining())
|
||||
{
|
||||
buffer = MemoryUtil.memAlloc(LodBufferContainer.FULL_SIZED_BUFFER);
|
||||
buffer = MemoryUtil.memAlloc(getMaxBufferByteSize());
|
||||
byteBufferList.add(buffer);
|
||||
}
|
||||
|
||||
@@ -481,17 +485,29 @@ public class LodQuadBuilder
|
||||
return i;
|
||||
}
|
||||
|
||||
/** Returns how many GpuBuffers will be needed to render opaque quads in this builder. */
|
||||
public int getCurrentNeededOpaqueVertexBufferCount() { return MathUtil.ceilDiv(this.getCurrentOpaqueQuadsCount(), LodBufferContainer.MAX_QUADS_PER_BUFFER); }
|
||||
/** Returns how many GpuBuffers will be needed to render transparent quads in this builder. */
|
||||
public int getCurrentNeededTransparentVertexBufferCount()
|
||||
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 (!this.doTransparency)
|
||||
if (maxBufferByteSize != -1)
|
||||
{
|
||||
return 0;
|
||||
return maxBufferByteSize;
|
||||
}
|
||||
|
||||
return MathUtil.ceilDiv(this.getCurrentTransparentQuadsCount(), LodBufferContainer.MAX_QUADS_PER_BUFFER);
|
||||
// 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;
|
||||
|
||||
maxBufferByteSize = FULL_SIZED_BUFFER;
|
||||
|
||||
return FULL_SIZED_BUFFER;
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
+1
-9
@@ -9,8 +9,6 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
|
||||
import java.io.File;
|
||||
@@ -22,7 +20,7 @@ import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class DataMigratorV1 implements IDebugRenderable, AutoCloseable
|
||||
public class DataMigratorV1 implements AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
@@ -332,12 +330,6 @@ public class DataMigratorV1 implements IDebugRenderable, AutoCloseable
|
||||
// overrides //
|
||||
//===========//
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer renderer)
|
||||
{
|
||||
// nothing currently needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
|
||||
+9
-5
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.file.fullDatafile.V2;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.IDataSourceUpdateListenerFunc;
|
||||
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
|
||||
@@ -30,7 +31,7 @@ import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
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.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||
@@ -56,7 +57,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_WIREFRAME_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
private static final Set<String> CORRUPT_DATA_ERRORS_LOGGED = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
/**
|
||||
@@ -108,7 +111,7 @@ public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable
|
||||
this.updatePropagator = new FullDataUpdatePropagatorV2(this, this.dataUpdater, this.levelId);
|
||||
this.dataMigratorV1 = new DataMigratorV1(this.dataUpdater, this.level, this.levelId, this.saveDir);
|
||||
|
||||
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataUpdateStatus);
|
||||
DEBUG_WIREFRAME_RENDERER.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataUpdateStatus);
|
||||
|
||||
}
|
||||
|
||||
@@ -447,11 +450,10 @@ public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable
|
||||
//===========//
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer renderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer renderer)
|
||||
{
|
||||
this.dataUpdater.debugRender(renderer);
|
||||
this.updatePropagator.debugRender(renderer);
|
||||
this.dataMigratorV1.debugRender(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -465,6 +467,8 @@ public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable
|
||||
this.updatePropagator.close();
|
||||
this.dataMigratorV1.close();
|
||||
|
||||
DEBUG_WIREFRAME_RENDERER.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataUpdateStatus);
|
||||
|
||||
this.repo.close();
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -7,7 +7,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.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
|
||||
@@ -388,10 +388,10 @@ public class FullDataUpdatePropagatorV2 implements IDebugRenderable, AutoCloseab
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer renderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer renderer)
|
||||
{
|
||||
this.updatingPosSet
|
||||
.forEach((pos) -> { renderer.renderBox(new DebugRenderer.Box(pos, -32f, 80f, 0.20f, Color.MAGENTA)); });
|
||||
.forEach((pos) -> { renderer.renderBox(new AbstractDebugWireframeRenderer.Box(pos, -32f, 80f, 0.20f, Color.MAGENTA)); });
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-8
@@ -7,7 +7,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.IDataSourceUpdateListen
|
||||
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.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||
import com.seibel.distanthorizons.core.util.threading.PositionalLockProvider;
|
||||
@@ -225,20 +225,18 @@ public class FullDataUpdaterV2 implements IDebugRenderable, AutoCloseable
|
||||
//===========//
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer renderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer renderer)
|
||||
{
|
||||
this.lockedPosSet
|
||||
.forEach((pos) -> { renderer.renderBox(new DebugRenderer.Box(pos, -32f, 74f, 0.15f, Color.PINK)); });
|
||||
.forEach((pos) -> { renderer.renderBox(new AbstractDebugWireframeRenderer.Box(pos, -32f, 74f, 0.15f, Color.PINK)); });
|
||||
|
||||
this.queuedUpdateCountsByPos
|
||||
.forEach((pos, updateCountRef) -> { renderer.renderBox(new DebugRenderer.Box(pos, -32f, 80f + (updateCountRef.get() * 16f), 0.20f, Color.WHITE)); });
|
||||
.forEach((pos, updateCountRef) -> { renderer.renderBox(new AbstractDebugWireframeRenderer.Box(pos, -32f, 80f + (updateCountRef.get() * 16f), 0.20f, Color.WHITE)); });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
this.isShutdownRef.set(true);
|
||||
}
|
||||
public void close() { this.isShutdownRef.set(true); }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
package com.seibel.distanthorizons.core.generation;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
@@ -52,6 +53,8 @@ public class DhLightingEngine
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
public static final DhLightingEngine INSTANCE = new DhLightingEngine();
|
||||
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
/**
|
||||
* Minor garbage collection optimization. <br>
|
||||
* Since these objects are always mutated anyway, using a {@link ThreadLocal} will allow us to
|
||||
@@ -725,9 +728,9 @@ public class DhLightingEngine
|
||||
// a color can be set to null if you only want to troubleshoot up to a certain light level
|
||||
if (color != null)
|
||||
{
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(DhSectionPos.encode((byte) 0, chunkMinX + x, chunkMinZ + z), y, y + 1, 0.2f, color),
|
||||
DEBUG_RENDERER.makeParticle(
|
||||
new AbstractDebugWireframeRenderer.BoxParticle(
|
||||
new AbstractDebugWireframeRenderer.Box(DhSectionPos.encode((byte) 0, chunkMinX + x, chunkMinZ + z), y, y + 1, 0.2f, color),
|
||||
10.0, 0f
|
||||
)
|
||||
);
|
||||
|
||||
+7
-6
@@ -36,7 +36,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.transformers.LodDataBuilder;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.util.ExceptionUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil.AssertFailureException;
|
||||
@@ -61,6 +61,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final IWrapperFactory WRAPPER_FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
|
||||
private final IDhApiWorldGenerator generator;
|
||||
@@ -110,7 +111,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
this.lowestDataDetail = generator.getLargestDataDetailLevel();
|
||||
this.highestDataDetail = generator.getSmallestDataDetailLevel();
|
||||
|
||||
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue);
|
||||
DEBUG_RENDERER.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue);
|
||||
LOGGER.info("Created world gen queue");
|
||||
}
|
||||
|
||||
@@ -623,7 +624,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
///region debug
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer renderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer renderer)
|
||||
{
|
||||
int levelMinY = this.level.getLevelWrapper().getMinHeight();
|
||||
int levelMaxY = this.level.getLevelWrapper().getMaxHeight();
|
||||
@@ -638,7 +639,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
this.waitingTasks.keySet().forEach((Long pos) ->
|
||||
{
|
||||
renderer.renderBox(
|
||||
new DebugRenderer.Box(pos, levelMinY, maxY, 0.05f, Color.blue)
|
||||
new AbstractDebugWireframeRenderer.Box(pos, levelMinY, maxY, 0.05f, Color.blue)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -646,7 +647,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
this.inProgressGenTasksByLodPos.forEach((Long pos, DataSourceRetrievalTask task) ->
|
||||
{
|
||||
renderer.renderBox(
|
||||
new DebugRenderer.Box(pos, levelMinY, maxY, 0.05f, Color.red)
|
||||
new AbstractDebugWireframeRenderer.Box(pos, levelMinY, maxY, 0.05f, Color.red)
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -732,7 +733,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
|
||||
|
||||
this.generator.close();
|
||||
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue);
|
||||
DEBUG_RENDERER.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue);
|
||||
|
||||
|
||||
try
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.level;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkModifiedEvent;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.render.renderer.CloudRenderHandler;
|
||||
import com.seibel.distanthorizons.core.util.delayedSaveCache.DelayedBeaconSaveCache;
|
||||
import com.seibel.distanthorizons.core.util.delayedSaveCache.DelayedDataSourceSaveCache;
|
||||
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
|
||||
@@ -29,8 +30,6 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.CloudRenderHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||
@@ -39,6 +38,7 @@ import com.seibel.distanthorizons.core.sql.repo.ChunkHashRepo;
|
||||
import com.seibel.distanthorizons.core.util.KeyedLockContainer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -118,7 +118,7 @@ public abstract class AbstractDhLevel implements IDhLevel
|
||||
/** handles any setup that needs the repos to be created */
|
||||
protected void runRepoReliantSetup()
|
||||
{
|
||||
GenericObjectRenderer genericRenderer = this.getGenericRenderer();
|
||||
IDhGenericRenderer genericRenderer = this.getGenericRenderer();
|
||||
if (genericRenderer != null)
|
||||
{
|
||||
// only client levels can render clouds
|
||||
|
||||
@@ -28,9 +28,10 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.render.QuadTree.LodQuadTree;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
@@ -43,6 +44,7 @@ public class ClientLevelModule implements Closeable, IDataSourceUpdateListenerFu
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IWrapperFactory WRAPPER_FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
|
||||
private final IDhClientLevel clientLevel;
|
||||
|
||||
@@ -51,12 +53,12 @@ public class ClientLevelModule implements Closeable, IDataSourceUpdateListenerFu
|
||||
public final AtomicReference<ClientRenderState> ClientRenderStateRef = new AtomicReference<>();
|
||||
/**
|
||||
* This is handled outside of the {@link ClientRenderState} to prevent destroying
|
||||
* the {@link GenericObjectRenderer} when changing render distances or enabling/disabling rendering. <br><br>
|
||||
* the {@link IDhGenericRenderer} when changing render distances or enabling/disabling rendering. <br><br>
|
||||
*
|
||||
* Destroying the {@link GenericObjectRenderer} would cause any existing bindings to be
|
||||
* Destroying the {@link IDhGenericRenderer} would cause any existing bindings to be
|
||||
* erroneously removed.
|
||||
*/
|
||||
public final GenericObjectRenderer genericRenderer = new GenericObjectRenderer();
|
||||
public final IDhGenericRenderer genericRenderer = WRAPPER_FACTORY.createGenericRenderer();
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,19 +36,17 @@ import com.seibel.distanthorizons.core.network.event.ScopedNetworkEventSource;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataPartialUpdateMessage;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
@@ -298,7 +296,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
public ISaveStructure getSaveStructure() { return this.saveStructure; }
|
||||
|
||||
@Override
|
||||
public GenericObjectRenderer getGenericRenderer() { return this.clientside.genericRenderer; }
|
||||
public IDhGenericRenderer getGenericRenderer() { return this.clientside.genericRenderer; }
|
||||
@Override
|
||||
public RenderBufferHandler getRenderBufferHandler()
|
||||
{
|
||||
|
||||
@@ -19,21 +19,17 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.level;
|
||||
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
|
||||
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
|
||||
import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerStateManager;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
@@ -138,7 +134,7 @@ public class DhClientServerLevel extends AbstractDhServerLevel implements IDhCli
|
||||
|
||||
|
||||
@Override
|
||||
public GenericObjectRenderer getGenericRenderer() { return this.clientside.genericRenderer; }
|
||||
public IDhGenericRenderer getGenericRenderer() { return this.clientside.genericRenderer; }
|
||||
@Override
|
||||
public RenderBufferHandler getRenderBufferHandler()
|
||||
{
|
||||
|
||||
@@ -23,9 +23,8 @@ import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
|
||||
import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerStateManager;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
@@ -69,7 +68,7 @@ public class DhServerLevel extends AbstractDhServerLevel
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public GenericObjectRenderer getGenericRenderer()
|
||||
public IDhGenericRenderer getGenericRenderer()
|
||||
{
|
||||
// server-only levels don't support rendering
|
||||
return null;
|
||||
|
||||
@@ -27,10 +27,10 @@ import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataSource
|
||||
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -92,7 +92,7 @@ public interface IDhLevel extends AutoCloseable, GeneratedFullDataSourceProvider
|
||||
* Not supported on the server-side.
|
||||
*/
|
||||
@Nullable
|
||||
GenericObjectRenderer getGenericRenderer();
|
||||
IDhGenericRenderer getGenericRenderer();
|
||||
/**
|
||||
* Will return null if the renderer isn't set up yet. <br>
|
||||
* Not supported on the server-side.
|
||||
|
||||
@@ -31,18 +31,18 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.objects.pooling.PhantomArrayListPool;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
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;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
public class F3Screen
|
||||
{
|
||||
@@ -84,6 +84,7 @@ public class F3Screen
|
||||
{
|
||||
String r = MinecraftTextFormat.RED;
|
||||
String y = MinecraftTextFormat.YELLOW;
|
||||
String a = MinecraftTextFormat.AQUA;
|
||||
String cf = MinecraftTextFormat.CLEAR_FORMATTING;
|
||||
|
||||
|
||||
@@ -124,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("");
|
||||
}
|
||||
@@ -203,7 +207,7 @@ public class F3Screen
|
||||
}
|
||||
|
||||
// Generic rendering
|
||||
GenericObjectRenderer genericRenderer = level.getGenericRenderer();
|
||||
IDhGenericRenderer genericRenderer = level.getGenericRenderer();
|
||||
if (genericRenderer != null)
|
||||
{
|
||||
messageList.add(genericRenderer.getVboRenderDebugMenuString());
|
||||
|
||||
+6
-8
@@ -18,7 +18,7 @@ import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSourceR
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataSourceResponseMessage;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
@@ -43,6 +43,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
||||
.build();
|
||||
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
private static final int MAX_RETRY_ATTEMPTS = 3;
|
||||
|
||||
@@ -86,7 +87,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
||||
this.level = level;
|
||||
this.changedOnly = changedOnly;
|
||||
this.showDebugWireframeConfig = showDebugWireframeConfig;
|
||||
DebugRenderer.register(this, this.showDebugWireframeConfig);
|
||||
DEBUG_RENDERER.register(this, this.showDebugWireframeConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -385,10 +386,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
DebugRenderer.unregister(this, this.showDebugWireframeConfig);
|
||||
}
|
||||
public void close() { DEBUG_RENDERER.unregister(this, this.showDebugWireframeConfig); }
|
||||
|
||||
|
||||
|
||||
@@ -397,7 +395,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
||||
//===========//
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer renderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer renderer)
|
||||
{
|
||||
if (MC_CLIENT.getWrappedClientLevel() != this.level.getClientLevelWrapper())
|
||||
{
|
||||
@@ -428,7 +426,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
||||
}
|
||||
}
|
||||
|
||||
renderer.renderBox(new DebugRenderer.Box(pos, -32f, 64f, 0.05f, color));
|
||||
renderer.renderBox(new AbstractDebugWireframeRenderer.Box(pos, -32f, 64f, 0.05f, color));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,9 @@ import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Used to interact with Distant Horizons' rendering systems.
|
||||
@@ -83,16 +81,19 @@ public class DhApiRenderProxy implements IDhApiRenderProxy
|
||||
}
|
||||
|
||||
|
||||
public static int activeOpenGlDhDepthTextureId = -1;
|
||||
@Override
|
||||
public DhApiResult<Integer> getDhDepthTextureId()
|
||||
{
|
||||
int activeTexture = LodRenderer.INSTANCE.getActiveDepthTextureId();
|
||||
int activeTexture = activeOpenGlDhDepthTextureId;
|
||||
return (activeTexture == -1) ? DhApiResult.createFail("DH's depth texture hasn't been created and/or bound yet.", -1) : DhApiResult.createSuccess(activeTexture);
|
||||
}
|
||||
|
||||
public static int activeOpenGlDhColorTextureId = -1;
|
||||
@Override
|
||||
public DhApiResult<Integer> getDhColorTextureId()
|
||||
{
|
||||
int activeTexture = LodRenderer.INSTANCE.getActiveColorTextureId();
|
||||
int activeTexture = activeOpenGlDhColorTextureId;
|
||||
return (activeTexture == -1) ? DhApiResult.createFail("DH's color texture hasn't been created and/or bound yet.", -1) : DhApiResult.createSuccess(activeTexture);
|
||||
}
|
||||
|
||||
|
||||
+12
-8
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.render.QuadTree;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.config.listeners.IConfigListener;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProviderV2;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataUpdatePropagatorV2;
|
||||
@@ -33,10 +34,9 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.BeaconRenderHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.util.WorldGenUtil;
|
||||
@@ -44,6 +44,7 @@ import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
|
||||
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadTree;
|
||||
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
@@ -67,6 +68,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRenderable, IConfigListener, AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
/** there should only ever be one {@link LodQuadTree} so having the thread static should be fine */
|
||||
private static final ThreadPoolExecutor FULL_DATA_RETRIEVAL_QUEUE_THREAD = ThreadUtil.makeSingleThreadPool("LodQuadTree Data Retrieval Queue");
|
||||
|
||||
@@ -135,13 +139,13 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
{
|
||||
super(viewDiameterInBlocks, new DhBlockPos2D(initialPlayerBlockX, initialPlayerBlockZ), DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
|
||||
|
||||
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus);
|
||||
DEBUG_RENDERER.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus);
|
||||
|
||||
this.level = level;
|
||||
this.fullDataSourceProvider = fullDataSourceProvider;
|
||||
this.blockRenderDistanceDiameter = viewDiameterInBlocks;
|
||||
|
||||
GenericObjectRenderer genericObjectRenderer = this.level.getGenericRenderer();
|
||||
IDhGenericRenderer genericObjectRenderer = this.level.getGenericRenderer();
|
||||
this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null;
|
||||
|
||||
Config.Common.WorldGenerator.enableDistantGeneration.addListener(this);
|
||||
@@ -973,7 +977,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
//region debugging
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer debugRenderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer debugRenderer)
|
||||
{
|
||||
this.populateListWithEnabledRenderSections(this.debugNodeList);
|
||||
|
||||
@@ -1012,7 +1016,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
int levelHeightRange = (levelMaxY - levelMinY);
|
||||
int maxY = levelMaxY - (levelHeightRange / 2);
|
||||
|
||||
debugRenderer.renderBox(new DebugRenderer.Box(renderSection.pos, levelMinY, maxY, 0.05f, color));
|
||||
debugRenderer.renderBox(new AbstractDebugWireframeRenderer.Box(renderSection.pos, levelMinY, maxY, 0.05f, color));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1034,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
{
|
||||
LOGGER.info("Shutting down LodQuadTree...");
|
||||
|
||||
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus);
|
||||
DEBUG_RENDERER.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus);
|
||||
Config.Common.WorldGenerator.enableDistantGeneration.removeListener(this);
|
||||
Config.Server.enableServerGeneration.removeListener(this);
|
||||
|
||||
|
||||
+13
-20
@@ -33,11 +33,10 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.BeaconRenderHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
@@ -62,6 +61,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final AbstractDebugWireframeRenderer DEBUG_RENDERER = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
this.beaconRenderHandler = this.quadTree.beaconRenderHandler;
|
||||
this.beaconBeamRepo = this.level.getBeaconBeamRepo();
|
||||
|
||||
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
|
||||
DEBUG_RENDERER.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
|
||||
}
|
||||
|
||||
//endregion constructor
|
||||
@@ -152,13 +152,6 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
/** @return true if the upload started, false if it wasn't able to for any reason */
|
||||
public synchronized boolean uploadRenderDataToGpuAsync()
|
||||
{
|
||||
if (!GLProxy.hasInstance())
|
||||
{
|
||||
// it's possible to try uploading buffers before the GLProxy has been initialized
|
||||
// which would cause the system to crash
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getAndBuildRenderDataFutureRef.get() != null)
|
||||
{
|
||||
// don't accidentally queue multiple uploads at the same time
|
||||
@@ -452,9 +445,9 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
if (Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get())
|
||||
{
|
||||
// show that this position has just been disabled
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.CYAN.darker()),
|
||||
DEBUG_RENDERER.makeParticle(
|
||||
new AbstractDebugWireframeRenderer.BoxParticle(
|
||||
new AbstractDebugWireframeRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.CYAN.darker()),
|
||||
0.2, 32f
|
||||
)
|
||||
);
|
||||
@@ -513,7 +506,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
//region base methods
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer debugRenderer)
|
||||
public void debugRender(AbstractDebugWireframeRenderer debugRenderer)
|
||||
{
|
||||
Color color = Color.red;
|
||||
if (this.renderingEnabled)
|
||||
@@ -539,7 +532,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
int levelHeightRange = (levelMaxY - levelMinY);
|
||||
int maxY = levelMaxY - (levelHeightRange / 2);
|
||||
|
||||
debugRenderer.renderBox(new DebugRenderer.Box(this.pos, levelMinY, maxY, 0.01f, color));
|
||||
debugRenderer.renderBox(new AbstractDebugWireframeRenderer.Box(this.pos, levelMinY, maxY, 0.01f, color));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -555,14 +548,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
|
||||
DEBUG_RENDERER.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
|
||||
|
||||
if (Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get())
|
||||
{
|
||||
// show a particle for the closed section
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.RED.darker()),
|
||||
DEBUG_RENDERER.makeParticle(
|
||||
new AbstractDebugWireframeRenderer.BoxParticle(
|
||||
new AbstractDebugWireframeRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.RED.darker()),
|
||||
0.5, 32f
|
||||
)
|
||||
);
|
||||
|
||||
@@ -34,7 +34,8 @@ 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.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.RenderParams;
|
||||
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;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
package com.seibel.distanthorizons.core.render;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
@@ -7,8 +7,6 @@ import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
@@ -19,6 +17,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftCli
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
|
||||
/**
|
||||
@@ -41,12 +40,12 @@ public class RenderParams extends DhApiRenderParam
|
||||
public IClientLevelWrapper clientLevelWrapper;
|
||||
public ILightMapWrapper lightmap;
|
||||
public RenderBufferHandler renderBufferHandler;
|
||||
public GenericObjectRenderer genericRenderer;
|
||||
public IDhGenericRenderer genericRenderer;
|
||||
public Vec3d exactCameraPosition;
|
||||
/** @see DhRenderState#vanillaFogEnabled */
|
||||
public boolean vanillaFogEnabled;
|
||||
|
||||
public boolean validationRun = false;
|
||||
public boolean hasBeenValidated = false;
|
||||
|
||||
|
||||
|
||||
@@ -121,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())
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
package com.seibel.distanthorizons.core.render;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
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.util.TimerUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class RenderThreadTaskHandler
|
||||
{
|
||||
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
|
||||
.build();
|
||||
|
||||
private static final ConcurrentLinkedQueue<Runnable> RENDER_THREAD_RUNNABLE_QUEUE = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private static final Timer TIMER = TimerUtil.CreateTimer("Cleanup timer");
|
||||
private static final long MS_BETWEEN_CLEANUP_TICKS = 1_000L;
|
||||
private static final long MS_BEFORE_RUN_CLEANUP_TIMER = 1_000L;
|
||||
|
||||
|
||||
public static final RenderThreadTaskHandler INSTANCE = new RenderThreadTaskHandler();
|
||||
|
||||
|
||||
private long msSinceGlTasksRun = System.currentTimeMillis();
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
private RenderThreadTaskHandler() { TIMER.scheduleAtFixedRate(TimerUtil.createTimerTask(this::manualCleanupTick), MS_BETWEEN_CLEANUP_TICKS, MS_BETWEEN_CLEANUP_TICKS); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// task queuing //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
public void queueRunningOnRenderThread(Runnable renderCall)
|
||||
{
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
RENDER_THREAD_RUNNABLE_QUEUE.add(() -> this.createRenderThreadRunnable(renderCall, stackTrace));
|
||||
}
|
||||
private void createRenderThreadRunnable(Runnable renderCall, StackTraceElement[] stackTrace)
|
||||
{
|
||||
try
|
||||
{
|
||||
renderCall.run();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
RuntimeException error = new RuntimeException("Uncaught Exception during GL call execution:", e);
|
||||
error.setStackTrace(stackTrace);
|
||||
LOGGER.error("[" + Thread.currentThread().getName() + "] ran into an unexpected error running a GL call, Error: ["+ e.getMessage() +"].", error);
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// run tasks //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
/**
|
||||
* Doesn't do any thread/GL Context validation.
|
||||
* Running this outside of the render thread may cause crashes or other issues.
|
||||
*/
|
||||
public void runRenderThreadTasks()
|
||||
{
|
||||
IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
int frameLimit = MC_RENDER.getFrameLimit();
|
||||
if (frameLimit <= 1)
|
||||
{
|
||||
frameLimit = 4; // 240 FPS
|
||||
}
|
||||
|
||||
// https://fpstoms.com/
|
||||
int msPerFrame = 1000 / frameLimit;
|
||||
this.runRenderThreadTasks(msPerFrame);
|
||||
}
|
||||
private void runRenderThreadTasks(long msMaxRunTime)
|
||||
{
|
||||
long startTimeMs = System.currentTimeMillis();
|
||||
this.msSinceGlTasksRun = startTimeMs;
|
||||
|
||||
Runnable runnable = RENDER_THREAD_RUNNABLE_QUEUE.poll();
|
||||
while(runnable != null)
|
||||
{
|
||||
runnable.run();
|
||||
|
||||
// only try running for a limited amount of time to prevent lag spikes
|
||||
long currentTimeMs = System.currentTimeMillis();
|
||||
long runDuration = currentTimeMs - startTimeMs;
|
||||
if (runDuration > msMaxRunTime)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
runnable = RENDER_THREAD_RUNNABLE_QUEUE.poll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should only be called if our render code isn't being hit for some reason.
|
||||
* Normally this only happens if there's a mod that limits MC's framerate to 0.
|
||||
*/
|
||||
private void manualCleanupTick()
|
||||
{
|
||||
long nowMs = System.currentTimeMillis();
|
||||
long msSinceLast = nowMs - this.msSinceGlTasksRun;
|
||||
if (msSinceLast > MS_BEFORE_RUN_CLEANUP_TIMER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We haven't gotten a frame for a while,
|
||||
// this means we could have GL jobs building up.
|
||||
// Run the queued tasks on MC's executor (hopefully this should always run,
|
||||
// even if DH's render code isn't being hit).
|
||||
IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
MC.executeOnRenderThread(() -> this.runRenderThreadTasks(1_000));
|
||||
}
|
||||
|
||||
//end region
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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.fog;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogFalloff;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Contains all configurable options related to fog.
|
||||
*
|
||||
* @version 2022-4-13
|
||||
*/
|
||||
public class FogSettings
|
||||
{
|
||||
/** a FogSetting object with 0 for every value */
|
||||
public static final FogSettings EMPTY = new FogSettings(0, 0, 0, 0, 0, EDhApiFogFalloff.LINEAR);
|
||||
|
||||
|
||||
public final double start;
|
||||
public final double end;
|
||||
public final double min;
|
||||
public final double max;
|
||||
public final double density;
|
||||
public final EDhApiFogFalloff fogType;
|
||||
|
||||
public FogSettings(double start, double end, double min, double max, double density, EDhApiFogFalloff fogType)
|
||||
{
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.density = density;
|
||||
this.fogType = fogType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
FogSettings that = (FogSettings) o;
|
||||
return Double.compare(that.start, start) == 0 && Double.compare(that.end, end) == 0 && Double.compare(that.min, min) == 0 && Double.compare(that.max, max) == 0 && Double.compare(that.density, density) == 0 && fogType == that.fogType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(start, end, min, max, density, fogType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
/*
|
||||
* 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.glObject;
|
||||
|
||||
import static org.lwjgl.opengl.GL46.*;
|
||||
|
||||
// Turns GL int enums back to readable strings
|
||||
public class GLEnums
|
||||
{
|
||||
|
||||
public static String getString(int glEnum)
|
||||
{
|
||||
// blend stuff
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_ZERO:
|
||||
return "GL_ZERO";
|
||||
case GL_ONE:
|
||||
return "GL_ONE";
|
||||
case GL_SRC_COLOR:
|
||||
return "GL_SRC_COLOR";
|
||||
case GL_ONE_MINUS_SRC_COLOR:
|
||||
return "GL_ONE_MINUS_SRC_COLOR";
|
||||
case GL_DST_COLOR:
|
||||
return "GL_DST_COLOR";
|
||||
case GL_ONE_MINUS_DST_COLOR:
|
||||
return "GL_ONE_MINUS_DST_COLOR";
|
||||
case GL_SRC_ALPHA:
|
||||
return "GL_SRC_ALPHA";
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
return "GL_ONE_MINUS_SRC_ALPHA";
|
||||
case GL_DST_ALPHA:
|
||||
return "GL_DST_ALPHA";
|
||||
case GL_ONE_MINUS_DST_ALPHA:
|
||||
return "GL_ONE_MINUS_DST_ALPHA";
|
||||
case GL_CONSTANT_COLOR:
|
||||
return "GL_CONSTANT_COLOR";
|
||||
case GL_ONE_MINUS_CONSTANT_COLOR:
|
||||
return "GL_ONE_MINUS_CONSTANT_COLOR";
|
||||
case GL_CONSTANT_ALPHA:
|
||||
return "GL_CONSTANT_ALPHA";
|
||||
case GL_ONE_MINUS_CONSTANT_ALPHA:
|
||||
return "GL_ONE_MINUS_CONSTANT_ALPHA";
|
||||
default:
|
||||
}
|
||||
|
||||
// shader stuff
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_VERTEX_SHADER:
|
||||
return "GL_VERTEX_SHADER";
|
||||
case GL_GEOMETRY_SHADER:
|
||||
return "GL_GEOMETRY_SHADER";
|
||||
case GL_FRAGMENT_SHADER:
|
||||
return "GL_FRAGMENT_SHADER";
|
||||
default:
|
||||
}
|
||||
|
||||
// stencil stuff
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_KEEP:
|
||||
return "GL_KEEP";
|
||||
case GL_ZERO:
|
||||
return "GL_ZERO";
|
||||
case GL_REPLACE:
|
||||
return "GL_REPLACE";
|
||||
case GL_INCR:
|
||||
return "GL_INCR";
|
||||
case GL_DECR:
|
||||
return "GL_DECR";
|
||||
case GL_INVERT:
|
||||
return "GL_INVERT";
|
||||
case GL_INCR_WRAP:
|
||||
return "GL_INCR_WRAP";
|
||||
case GL_DECR_WRAP:
|
||||
return "GL_DECR_WRAP";
|
||||
default:
|
||||
}
|
||||
|
||||
// depth stuff
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_NEVER:
|
||||
return "GL_NEVER";
|
||||
case GL_LESS:
|
||||
return "GL_LESS";
|
||||
case GL_EQUAL:
|
||||
return "GL_EQUAL";
|
||||
case GL_LEQUAL:
|
||||
return "GL_LEQUAL";
|
||||
case GL_GREATER:
|
||||
return "GL_GREATER";
|
||||
case GL_NOTEQUAL:
|
||||
return "GL_NOTEQUAL";
|
||||
case GL_GEQUAL:
|
||||
return "GL_GEQUAL";
|
||||
case GL_ALWAYS:
|
||||
return "GL_ALWAYS";
|
||||
default:
|
||||
}
|
||||
|
||||
// Texture binding points
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_TEXTURE0:
|
||||
return "GL_TEXTURE0";
|
||||
case GL_TEXTURE1:
|
||||
return "GL_TEXTURE1";
|
||||
case GL_TEXTURE2:
|
||||
return "GL_TEXTURE2";
|
||||
case GL_TEXTURE3:
|
||||
return "GL_TEXTURE3";
|
||||
case GL_TEXTURE4:
|
||||
return "GL_TEXTURE4";
|
||||
case GL_TEXTURE5:
|
||||
return "GL_TEXTURE5";
|
||||
case GL_TEXTURE6:
|
||||
return "GL_TEXTURE6";
|
||||
case GL_TEXTURE7:
|
||||
return "GL_TEXTURE7";
|
||||
case GL_TEXTURE8:
|
||||
return "GL_TEXTURE8";
|
||||
case GL_TEXTURE9:
|
||||
return "GL_TEXTURE9";
|
||||
case GL_TEXTURE10:
|
||||
return "GL_TEXTURE10";
|
||||
case GL_TEXTURE11:
|
||||
return "GL_TEXTURE11";
|
||||
case GL_TEXTURE12:
|
||||
return "GL_TEXTURE12";
|
||||
case GL_TEXTURE13:
|
||||
return "GL_TEXTURE13";
|
||||
case GL_TEXTURE14:
|
||||
return "GL_TEXTURE14";
|
||||
case GL_TEXTURE15:
|
||||
return "GL_TEXTURE15";
|
||||
case GL_TEXTURE16:
|
||||
return "GL_TEXTURE16";
|
||||
case GL_TEXTURE17:
|
||||
return "GL_TEXTURE17";
|
||||
case GL_TEXTURE18:
|
||||
return "GL_TEXTURE18";
|
||||
case GL_TEXTURE19:
|
||||
return "GL_TEXTURE19";
|
||||
case GL_TEXTURE20:
|
||||
return "GL_TEXTURE20";
|
||||
case GL_TEXTURE21:
|
||||
return "GL_TEXTURE21";
|
||||
case GL_TEXTURE22:
|
||||
return "GL_TEXTURE22";
|
||||
case GL_TEXTURE23:
|
||||
return "GL_TEXTURE23";
|
||||
case GL_TEXTURE24:
|
||||
return "GL_TEXTURE24";
|
||||
case GL_TEXTURE25:
|
||||
return "GL_TEXTURE25";
|
||||
case GL_TEXTURE26:
|
||||
return "GL_TEXTURE26";
|
||||
case GL_TEXTURE27:
|
||||
return "GL_TEXTURE27";
|
||||
case GL_TEXTURE28:
|
||||
return "GL_TEXTURE28";
|
||||
case GL_TEXTURE29:
|
||||
return "GL_TEXTURE29";
|
||||
case GL_TEXTURE30:
|
||||
return "GL_TEXTURE30";
|
||||
case GL_TEXTURE31:
|
||||
return "GL_TEXTURE31";
|
||||
default:
|
||||
}
|
||||
|
||||
// Polygon modes
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_POINT:
|
||||
return "GL_POINT";
|
||||
case GL_LINE:
|
||||
return "GL_LINE";
|
||||
case GL_FILL:
|
||||
return "GL_FILL";
|
||||
default:
|
||||
}
|
||||
|
||||
// Culling modes
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_FRONT:
|
||||
return "GL_FRONT";
|
||||
case GL_BACK:
|
||||
return "GL_BACK";
|
||||
case GL_FRONT_AND_BACK:
|
||||
return "GL_FRONT_AND_BACK";
|
||||
default:
|
||||
}
|
||||
|
||||
// Types
|
||||
switch (glEnum)
|
||||
{
|
||||
case GL_BYTE:
|
||||
return "GL_BYTE";
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return "GL_UNSIGNED_BYTE";
|
||||
case GL_SHORT:
|
||||
return "GL_SHORT";
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return "GL_UNSIGNED_SHORT";
|
||||
case GL_INT:
|
||||
return "GL_INT";
|
||||
case GL_UNSIGNED_INT:
|
||||
return "GL_UNSIGNED_INT";
|
||||
case GL_FLOAT:
|
||||
return "GL_FLOAT";
|
||||
case GL_DOUBLE:
|
||||
return "GL_DOUBLE";
|
||||
default:
|
||||
}
|
||||
|
||||
return "GL_UNKNOWN(" + glEnum + ")";
|
||||
}
|
||||
|
||||
public static int getTypeSize(int glTypeEnum)
|
||||
{
|
||||
switch (glTypeEnum)
|
||||
{
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return 1;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return 2;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return 4;
|
||||
case GL_FLOAT:
|
||||
return 4;
|
||||
case GL_DOUBLE:
|
||||
return 8;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown type enum: " + getString(glTypeEnum));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
* 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.glObject;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGLErrorHandlingMode;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessages.*;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.opengl.GLUtil;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* A singleton that holds references to different openGL contexts
|
||||
* and GPU capabilities.
|
||||
*/
|
||||
public class GLProxy
|
||||
{
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||
.build();
|
||||
|
||||
public static final Set<String> LOGGED_GL_MESSAGES = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
|
||||
|
||||
private static final ConcurrentLinkedQueue<Runnable> RENDER_THREAD_RUNNABLE_QUEUE = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private static final Timer TIMER = TimerUtil.CreateTimer("Cleanup timer");
|
||||
private static final long MS_BETWEEN_CLEANUP_TICKS = 1_000L;
|
||||
private static final long MS_BEFORE_RUN_CLEANUP_TIMER = 1_000L;
|
||||
|
||||
|
||||
|
||||
private static GLProxy instance = null;
|
||||
|
||||
|
||||
/** Minecraft's GL capabilities */
|
||||
public final GLCapabilities glCapabilities;
|
||||
|
||||
public boolean namedObjectSupported = false; // ~OpenGL 4.5 (UNUSED CURRENTLY)
|
||||
public boolean bufferStorageSupported = false; // ~OpenGL 4.4
|
||||
public boolean vertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3
|
||||
public boolean instancedArraysSupported = false;
|
||||
public boolean vertexAttribDivisorSupported = false; // OpenGL 3.3 or newer
|
||||
|
||||
private final EDhApiGpuUploadMethod preferredUploadMethod;
|
||||
|
||||
public final GLMessageBuilder vanillaDebugMessageBuilder =
|
||||
new GLMessageBuilder(
|
||||
(type) ->
|
||||
{
|
||||
if (type == EGLMessageType.POP_GROUP)
|
||||
return false;
|
||||
else if (type == EGLMessageType.PUSH_GROUP)
|
||||
return false;
|
||||
else if (type == EGLMessageType.MARKER)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
},
|
||||
(severity) ->
|
||||
{
|
||||
// notifications can generally be ignored (if they are logged at all)
|
||||
if (severity == EGLMessageSeverity.NOTIFICATION)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
},
|
||||
null
|
||||
);
|
||||
|
||||
private long msSinceGlTasksRun = System.currentTimeMillis();
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
private GLProxy() throws IllegalStateException
|
||||
{
|
||||
// this must be created on minecraft's render context to work correctly
|
||||
if (GLFW.glfwGetCurrentContext() == 0L)
|
||||
{
|
||||
throw new IllegalStateException(GLProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||
}
|
||||
|
||||
LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error.");
|
||||
LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "].");
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// get Minecraft's GL context //
|
||||
//============================//
|
||||
|
||||
// get Minecraft's capabilities
|
||||
this.glCapabilities = GL.getCapabilities();
|
||||
|
||||
// crash the game if the GPU doesn't support OpenGL 3.2
|
||||
if (!this.glCapabilities.OpenGL32)
|
||||
{
|
||||
String supportedVersionInfo = this.getFailedVersionInfo(this.glCapabilities);
|
||||
|
||||
// See full requirement at above.
|
||||
String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GLProxy.class.getSimpleName()
|
||||
+ " and discovered this GPU doesn't meet the OpenGL requirements. Sorry I couldn't tell you sooner :(\n" +
|
||||
"Additional info:\n" + supportedVersionInfo;
|
||||
MC.crashMinecraft(errorMessage, new UnsupportedOperationException("Distant Horizon OpenGL requirements not met"));
|
||||
}
|
||||
LOGGER.info("minecraftGlCapabilities:\n" + this.versionInfoToString(this.glCapabilities));
|
||||
|
||||
if (Config.Client.Advanced.Debugging.OpenGl.overrideVanillaGLLogger.get())
|
||||
{
|
||||
GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream(GLProxy::logMessage, this.vanillaDebugMessageBuilder), true));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
// get GPU capabilities //
|
||||
//======================//
|
||||
|
||||
// UNUSED currently
|
||||
// Check if we can use the named version of all calls, which is available in GL4.5 or after
|
||||
this.namedObjectSupported = this.glCapabilities.glNamedBufferData != 0L; //Nullptr
|
||||
|
||||
// Check if we can use the Buffer Storage, which is available in GL4.4 or after
|
||||
this.bufferStorageSupported = this.glCapabilities.glBufferStorage != 0L; // Nullptr
|
||||
if (!this.bufferStorageSupported)
|
||||
{
|
||||
LOGGER.info("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods.");
|
||||
}
|
||||
|
||||
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
|
||||
this.vertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr
|
||||
|
||||
// used by instanced rendering
|
||||
this.vertexAttribDivisorSupported = this.glCapabilities.OpenGL33;
|
||||
// denotes if ARBInstancedArrays.glVertexAttribDivisorARB() is available or not
|
||||
// can be used as a backup if MC didn't create a GL 3.3+ context
|
||||
this.instancedArraysSupported = this.glCapabilities.GL_ARB_instanced_arrays;
|
||||
|
||||
// get the best automatic upload method
|
||||
String vendor = GL32.glGetString(GL32.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION"
|
||||
if (EPlatform.get() != EPlatform.MACOS)
|
||||
{
|
||||
if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE"))
|
||||
{
|
||||
// NVIDIA card
|
||||
this.preferredUploadMethod = this.bufferStorageSupported ? EDhApiGpuUploadMethod.BUFFER_STORAGE : EDhApiGpuUploadMethod.SUB_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
// AMD or Intel card
|
||||
this.preferredUploadMethod = this.bufferStorageSupported ? EDhApiGpuUploadMethod.BUFFER_STORAGE : EDhApiGpuUploadMethod.DATA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mac may have an issue with Buffer Storage, so default to the most basic
|
||||
// form of uploading
|
||||
this.preferredUploadMethod = EDhApiGpuUploadMethod.DATA;
|
||||
}
|
||||
LOGGER.info("GPU Vendor [" + vendor + "] with OS [" + EPlatform.get().getName() + "], Preferred upload method is [" + this.preferredUploadMethod + "].");
|
||||
|
||||
|
||||
TIMER.scheduleAtFixedRate(TimerUtil.createTimerTask(this::manualGlCleanupTick), MS_BETWEEN_CLEANUP_TICKS, MS_BETWEEN_CLEANUP_TICKS);
|
||||
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
//==========//
|
||||
|
||||
// GLProxy creation success
|
||||
LOGGER.info(GLProxy.class.getSimpleName() + " creation successful. OpenGL smiles upon you this day.");
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
public static boolean hasInstance() { return instance != null; }
|
||||
/** @throws IllegalStateException if the Proxy hasn't been created yet and this is called outside the render thread */
|
||||
public static GLProxy getInstance() throws IllegalStateException
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new GLProxy();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public EDhApiGpuUploadMethod getGpuUploadMethod()
|
||||
{
|
||||
EDhApiGpuUploadMethod uploadOverride = Config.Client.Advanced.Debugging.OpenGl.glUploadMode.get();
|
||||
if (uploadOverride == EDhApiGpuUploadMethod.AUTO)
|
||||
{
|
||||
return this.preferredUploadMethod;
|
||||
}
|
||||
|
||||
return uploadOverride;
|
||||
}
|
||||
|
||||
public static boolean runningOnRenderThread()
|
||||
{
|
||||
long currentContext = GLFW.glfwGetCurrentContext();
|
||||
return currentContext != 0L; // if the context isn't null, it's the MC context
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========================//
|
||||
// Worker Thread Runnables //
|
||||
//=========================//
|
||||
//region
|
||||
|
||||
public static void queueRunningOnRenderThread(Runnable renderCall)
|
||||
{
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
RENDER_THREAD_RUNNABLE_QUEUE.add(() -> runOpenGlCall(renderCall, stackTrace));
|
||||
}
|
||||
private static void runOpenGlCall(Runnable renderCall, StackTraceElement[] stackTrace)
|
||||
{
|
||||
try
|
||||
{
|
||||
renderCall.run();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
RuntimeException error = new RuntimeException("Uncaught Exception during GL call execution:", e);
|
||||
error.setStackTrace(stackTrace);
|
||||
LOGGER.error("[" + Thread.currentThread().getName() + "] ran into an unexpected error running a GL call, Error: ["+ e.getMessage() +"].", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Doesn't do any thread/GL Context validation.
|
||||
* Running this outside of the render thread may cause crashes or other issues.
|
||||
*/
|
||||
public void runRenderThreadTasks()
|
||||
{
|
||||
int frameLimit = MC_RENDER.getFrameLimit();
|
||||
if (frameLimit <= 1)
|
||||
{
|
||||
frameLimit = 4; // 240 FPS
|
||||
}
|
||||
|
||||
// https://fpstoms.com/
|
||||
int msPerFrame = 1000 / frameLimit;
|
||||
this.runRenderThreadTasks(msPerFrame);
|
||||
}
|
||||
private void runRenderThreadTasks(long msMaxRunTime)
|
||||
{
|
||||
long startTimeMs = System.currentTimeMillis();
|
||||
this.msSinceGlTasksRun = startTimeMs;
|
||||
|
||||
Runnable runnable = RENDER_THREAD_RUNNABLE_QUEUE.poll();
|
||||
while(runnable != null)
|
||||
{
|
||||
runnable.run();
|
||||
|
||||
// only try running for 4ms (240 FPS) at a time to prevent random lag spikes
|
||||
long currentTimeMs = System.currentTimeMillis();
|
||||
long runDuration = currentTimeMs - startTimeMs;
|
||||
if (runDuration > msMaxRunTime)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
runnable = RENDER_THREAD_RUNNABLE_QUEUE.poll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should only be called if our render code isn't being hit for some reason.
|
||||
* Normally this only happens if there's a mod that limits MC's framerate to 0.
|
||||
*/
|
||||
private void manualGlCleanupTick()
|
||||
{
|
||||
long nowMs = System.currentTimeMillis();
|
||||
long msSinceLast = nowMs - this.msSinceGlTasksRun;
|
||||
if (msSinceLast > MS_BEFORE_RUN_CLEANUP_TIMER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We haven't gotten a frame for a while,
|
||||
// this means we could have GL jobs building up.
|
||||
// Run the queued tasks on MC's executor (hopefully this should always run,
|
||||
// even if DH's render code isn't being hit).
|
||||
MC.executeOnRenderThread(() -> this.runRenderThreadTasks(1_000));
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// logging //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
/** this method is called on the render thread at the point of the GL Error */
|
||||
private static void logMessage(GLMessage msg)
|
||||
{
|
||||
EDhApiGLErrorHandlingMode errorHandlingMode = Config.Client.Advanced.Debugging.OpenGl.glErrorHandlingMode.get();
|
||||
if (errorHandlingMode == EDhApiGLErrorHandlingMode.IGNORE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean onlyLogOnce = Config.Client.Advanced.Debugging.OpenGl.onlyLogGlErrorsOnce.get();
|
||||
String errorMessage = "GL ERROR [" + msg.id + "] from [" + msg.source + "]: [" + msg.message + "]"+(onlyLogOnce ? " this message will only be logged once" : "")+".";
|
||||
if (onlyLogOnce
|
||||
&& !LOGGED_GL_MESSAGES.add(errorMessage))
|
||||
{
|
||||
// this message has already been logged
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create an exception so we get a stacktrace of where the message was triggered from
|
||||
RuntimeException exception = new RuntimeException(errorMessage);
|
||||
|
||||
if (msg.type == EGLMessageType.ERROR || msg.type == EGLMessageType.UNDEFINED_BEHAVIOR)
|
||||
{
|
||||
// critical error
|
||||
|
||||
LOGGER.error(exception.getMessage(), exception);
|
||||
|
||||
if (errorHandlingMode == EDhApiGLErrorHandlingMode.LOG_THROW)
|
||||
{
|
||||
// will probably crash the game,
|
||||
// good for quickly checking if there's a problem while preventing log spam
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-critical log
|
||||
|
||||
EGLMessageSeverity severity = msg.severity;
|
||||
if (severity == null)
|
||||
{
|
||||
// just in case the message was malformed
|
||||
severity = EGLMessageSeverity.LOW;
|
||||
}
|
||||
|
||||
switch (severity)
|
||||
{
|
||||
case HIGH:
|
||||
LOGGER.error(exception.getMessage(), exception);
|
||||
break;
|
||||
case MEDIUM:
|
||||
LOGGER.warn(exception.getMessage(), exception);
|
||||
break;
|
||||
case LOW:
|
||||
LOGGER.info(exception.getMessage(), exception);
|
||||
break;
|
||||
case NOTIFICATION:
|
||||
LOGGER.debug(exception.getMessage(), exception);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
//region
|
||||
|
||||
private String getFailedVersionInfo(GLCapabilities c)
|
||||
{
|
||||
return "Your OpenGL support:\n" +
|
||||
"openGL version 3.2+: [" + c.OpenGL32 + "] <- REQUIRED\n" +
|
||||
"Vertex Attribute Buffer Binding: [" + (c.glVertexAttribBinding != 0) + "] <- optional improvement\n" +
|
||||
"Buffer Storage: [" + (c.glBufferStorage != 0) + "] <- optional improvement\n" +
|
||||
"If you noticed that your computer supports higher OpenGL versions"
|
||||
+ " but not the required version, try running the game in compatibility mode."
|
||||
+ " (How you turn that on, I have no clue~)";
|
||||
}
|
||||
|
||||
private String versionInfoToString(GLCapabilities c)
|
||||
{
|
||||
return "Your OpenGL support:\n" +
|
||||
"openGL version 3.2+: [" + c.OpenGL32 + "] <- REQUIRED\n" +
|
||||
"Vertex Attribute Buffer Binding: [" + (c.glVertexAttribBinding != 0) + "] <- optional improvement\n" +
|
||||
"Buffer Storage: [" + (c.glBufferStorage != 0) + "] <- optional improvement\n";
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* 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.glObject;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class GLState implements AutoCloseable
|
||||
{
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public int program;
|
||||
public int vao;
|
||||
public int vbo;
|
||||
public int ebo;
|
||||
public int fbo;
|
||||
public int texture2D;
|
||||
/** IE: GL_TEXTURE0, GL_TEXTURE1, etc. */
|
||||
public int activeTextureNumber;
|
||||
public int texture0;
|
||||
public int texture1;
|
||||
public int texture2;
|
||||
public int texture3;
|
||||
public int frameBufferTexture0;
|
||||
public int frameBufferTexture1;
|
||||
public int frameBufferDepthTexture;
|
||||
public boolean blend;
|
||||
public boolean scissor;
|
||||
public int blendEqRGB;
|
||||
public int blendEqAlpha;
|
||||
public int blendSrcColor;
|
||||
public int blendSrcAlpha;
|
||||
public int blendDstColor;
|
||||
public int blendDstAlpha;
|
||||
public boolean depth;
|
||||
public boolean writeToDepthBuffer;
|
||||
public int depthFunc;
|
||||
public boolean stencil;
|
||||
public int stencilFunc;
|
||||
public int stencilRef;
|
||||
public int stencilMask;
|
||||
public int[] view;
|
||||
public boolean cull;
|
||||
public int cullMode;
|
||||
public int polyMode;
|
||||
|
||||
|
||||
|
||||
public GLState() { this.saveState(); }
|
||||
|
||||
public void saveState()
|
||||
{
|
||||
this.program = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM);
|
||||
this.vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
|
||||
this.vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||
this.ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING);
|
||||
|
||||
this.fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||
|
||||
this.texture2D = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||
this.activeTextureNumber = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
this.texture0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
this.texture1 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE2); // problem with Iris
|
||||
this.texture2 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE3);
|
||||
this.texture3 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||
|
||||
GLMC.glActiveTexture(this.activeTextureNumber);
|
||||
|
||||
if (this.fbo != 0)
|
||||
{
|
||||
this.frameBufferTexture0 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
this.frameBufferTexture1 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
this.frameBufferDepthTexture = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
// attempting to get values from the default framebuffer can throw errors on Linux
|
||||
this.frameBufferTexture0 = 0;
|
||||
this.frameBufferTexture1 = 0;
|
||||
this.frameBufferDepthTexture = 0;
|
||||
}
|
||||
|
||||
this.blend = GL32.glIsEnabled(GL32.GL_BLEND);
|
||||
this.scissor = GL32.glIsEnabled(GL32.GL_SCISSOR_TEST);
|
||||
this.blendEqRGB = GL32.glGetInteger(GL32.GL_BLEND_EQUATION_RGB);
|
||||
this.blendEqAlpha = GL32.glGetInteger(GL32.GL_BLEND_EQUATION_ALPHA);
|
||||
this.blendSrcColor = GL32.glGetInteger(GL32.GL_BLEND_SRC_RGB);
|
||||
this.blendSrcAlpha = GL32.glGetInteger(GL32.GL_BLEND_SRC_ALPHA);
|
||||
this.blendDstColor = GL32.glGetInteger(GL32.GL_BLEND_DST_RGB);
|
||||
this.blendDstAlpha = GL32.glGetInteger(GL32.GL_BLEND_DST_ALPHA);
|
||||
this.depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST);
|
||||
this.writeToDepthBuffer = GL32.glGetInteger(GL32.GL_DEPTH_WRITEMASK) == GL32.GL_TRUE;
|
||||
this.depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
|
||||
this.stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST);
|
||||
this.stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC);
|
||||
this.stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF);
|
||||
this.stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK);
|
||||
this.view = new int[4];
|
||||
GL32.glGetIntegerv(GL32.GL_VIEWPORT, this.view);
|
||||
this.cull = GL32.glIsEnabled(GL32.GL_CULL_FACE);
|
||||
this.cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE);
|
||||
this.polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
// explicitly unbinding the frame buffer is necessary to prevent GL_CLEAR calls from hitting the wrong buffer
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0);
|
||||
boolean frameBufferSet = false;
|
||||
|
||||
if (this.fbo != 0 && GL32.glIsFramebuffer(this.fbo))
|
||||
{
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fbo);
|
||||
frameBufferSet = true;
|
||||
}
|
||||
|
||||
|
||||
if (this.blend)
|
||||
{
|
||||
GLMC.enableBlend();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMC.disableBlend();
|
||||
}
|
||||
|
||||
if (this.scissor)
|
||||
{
|
||||
GLMC.enableScissorTest();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMC.disableScissorTest();
|
||||
}
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(GL32.glIsTexture(this.texture0) ? this.texture0 : 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(GL32.glIsTexture(this.texture1) ? this.texture1 : 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE2);
|
||||
GLMC.glBindTexture(GL32.glIsTexture(this.texture2) ? this.texture2 : 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE3);
|
||||
GLMC.glBindTexture(GL32.glIsTexture(this.texture3) ? this.texture3 : 0);
|
||||
|
||||
GLMC.glActiveTexture(this.activeTextureNumber);
|
||||
GLMC.glBindTexture(GL32.glIsTexture(this.texture2D) ? this.texture2D : 0);
|
||||
|
||||
// attempting to set textures on the default frame buffer (ID 0) will throw errors
|
||||
if (frameBufferSet)
|
||||
{
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0);
|
||||
}
|
||||
|
||||
GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, GL32.glIsBuffer(this.vbo) ? this.vbo : 0);
|
||||
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, GL32.glIsBuffer(this.ebo) ? this.ebo: 0);
|
||||
GL32.glUseProgram(GL32.glIsProgram(this.program) ? this.program : 0);
|
||||
|
||||
if (this.writeToDepthBuffer)
|
||||
{
|
||||
GLMC.enableDepthMask();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMC.disableDepthMask();
|
||||
}
|
||||
|
||||
GLMC.glBlendFunc(this.blendSrcColor, this.blendDstColor);
|
||||
GL32.glBlendEquationSeparate(this.blendEqRGB, this.blendEqAlpha);
|
||||
GLMC.glBlendFuncSeparate(this.blendSrcColor, this.blendDstColor, this.blendSrcAlpha, this.blendDstAlpha);
|
||||
|
||||
if (this.depth)
|
||||
{
|
||||
GLMC.enableDepthTest();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMC.disableDepthTest();
|
||||
}
|
||||
GLMC.glDepthFunc(this.depthFunc);
|
||||
|
||||
if (this.stencil)
|
||||
{
|
||||
GL32.glEnable(GL32.GL_STENCIL_TEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glDisable(GL32.GL_STENCIL_TEST);
|
||||
}
|
||||
GL32.glStencilFunc(this.stencilFunc, this.stencilRef, this.stencilMask);
|
||||
|
||||
GL32.glViewport(this.view[0], this.view[1], this.view[2], this.view[3]);
|
||||
if (this.cull)
|
||||
{
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMC.disableFaceCulling();
|
||||
}
|
||||
GL32.glCullFace(this.cullMode);
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "GLState{" +
|
||||
"program=" + this.program + ", vao=" + this.vao + ", vbo=" + this.vbo + ", ebo=" + this.ebo + ", fbo=" + this.fbo +
|
||||
", text=" + GLEnums.getString(this.texture2D) + "@" + this.activeTextureNumber + ", text0=" + GLEnums.getString(this.texture0) +
|
||||
", FB text0=" + this.frameBufferTexture0 +
|
||||
", FB text1=" + this.frameBufferTexture1 +
|
||||
", FB depth=" + this.frameBufferDepthTexture +
|
||||
", blend=" + this.blend + ", scissor=" + this.scissor + ", blendMode=" + GLEnums.getString(this.blendSrcColor) + "," + GLEnums.getString(this.blendDstColor) +
|
||||
", depth=" + this.depth +
|
||||
", depthFunc=" + GLEnums.getString(this.depthFunc) + ", stencil=" + this.stencil +
|
||||
", stencilFunc=" + GLEnums.getString(this.stencilFunc) + ", stencilRef=" + this.stencilRef + ", stencilMask=" + this.stencilMask +
|
||||
", view={x:" + this.view[0] + ", y:" + this.view[1] +
|
||||
", w:" + this.view[2] + ", h:" + this.view[3] + "}" + ", cull=" + this.cull +
|
||||
", cullMode=" + GLEnums.getString(this.cullMode) + ", polyMode=" + GLEnums.getString(this.polyMode) +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-344
@@ -1,344 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.buffer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
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.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL44;
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class GLBuffer implements AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||
.build();
|
||||
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public static final double BUFFER_EXPANSION_MULTIPLIER = 1.3;
|
||||
public static final double BUFFER_SHRINK_TRIGGER = BUFFER_EXPANSION_MULTIPLIER * BUFFER_EXPANSION_MULTIPLIER;
|
||||
/** the number of active buffers, can be used for debugging */
|
||||
public static AtomicInteger bufferCount = new AtomicInteger(0);
|
||||
|
||||
private static final int PHANTOM_REF_CHECK_TIME_IN_MS = 5 * 1000;
|
||||
private static final ConcurrentHashMap<PhantomReference<? extends GLBuffer>, Integer> PHANTOM_TO_BUFFER_ID = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer, PhantomReference<? extends GLBuffer>> BUFFER_ID_TO_PHANTOM = new ConcurrentHashMap<>();
|
||||
private static final ReferenceQueue<GLBuffer> PHANTOM_REFERENCE_QUEUE = new ReferenceQueue<>();
|
||||
private static final ThreadPoolExecutor CLEANUP_THREAD = ThreadUtil.makeSingleDaemonThreadPool("GLBuffer Cleanup");
|
||||
|
||||
|
||||
protected int id;
|
||||
public final int getId() { return this.id; }
|
||||
protected int size = 0;
|
||||
public int getSize() { return this.size; }
|
||||
protected boolean bufferStorage;
|
||||
public final boolean isBufferStorage() { return this.bufferStorage; }
|
||||
protected boolean isMapped = false;
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
static { CLEANUP_THREAD.execute(() -> runPhantomReferenceCleanupLoop()); }
|
||||
|
||||
public GLBuffer(boolean isBufferStorage) { this.create(isBufferStorage); }
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
// Should be override by subclasses
|
||||
public int getBufferBindingTarget() { return GL32.GL_COPY_READ_BUFFER; }
|
||||
|
||||
public void bind() { GL32.glBindBuffer(this.getBufferBindingTarget(), this.id); }
|
||||
public void unbind() { GL32.glBindBuffer(this.getBufferBindingTarget(), 0); }
|
||||
|
||||
|
||||
|
||||
//====================//
|
||||
// create and destroy //
|
||||
//====================//
|
||||
|
||||
protected void create(boolean asBufferStorage)
|
||||
{
|
||||
if (!GLProxy.runningOnRenderThread())
|
||||
{
|
||||
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
this.id = GLMC.glGenBuffers();
|
||||
this.bufferStorage = asBufferStorage;
|
||||
bufferCount.getAndIncrement();
|
||||
|
||||
PhantomReference<GLBuffer> phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE);
|
||||
PHANTOM_TO_BUFFER_ID.put(phantom, this.id);
|
||||
BUFFER_ID_TO_PHANTOM.put(this.id, phantom);
|
||||
|
||||
}
|
||||
|
||||
protected void destroyAsync()
|
||||
{
|
||||
if (this.id == 0)
|
||||
{
|
||||
// the buffer has already been closed
|
||||
return;
|
||||
}
|
||||
|
||||
destroyBufferIdAsync(this.id);
|
||||
|
||||
this.id = 0;
|
||||
this.size = 0;
|
||||
}
|
||||
private static void destroyBufferIdAsync(int id)
|
||||
{
|
||||
// remove and clear the phantom reference if present
|
||||
if (BUFFER_ID_TO_PHANTOM.containsKey(id))
|
||||
{
|
||||
Reference<? extends GLBuffer> phantom = BUFFER_ID_TO_PHANTOM.get(id);
|
||||
|
||||
// if we are manually closing this buffer, we don't want the phantom reference to accidentally close it again
|
||||
// this can cause a race condition were we accidentally delete an in-use buffer and cause NVIDIA
|
||||
// to throw an EXCEPTION_ACCESS_VIOLATION when we attempt to render it
|
||||
phantom.clear();
|
||||
|
||||
PHANTOM_TO_BUFFER_ID.remove(phantom);
|
||||
BUFFER_ID_TO_PHANTOM.remove(id);
|
||||
}
|
||||
|
||||
GLProxy.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// buffer uploading //
|
||||
//==================//
|
||||
|
||||
/**
|
||||
* Assumes the GL Context is already bound. <br>
|
||||
* Will create the VBO if one exist.
|
||||
*/
|
||||
public void uploadBuffer(ByteBuffer bb, EDhApiGpuUploadMethod uploadMethod, int maxExpansionSize, int bufferHint)
|
||||
{
|
||||
LodUtil.assertTrue(!uploadMethod.useEarlyMapping, "UploadMethod signal that this should use Mapping instead of uploadBuffer!");
|
||||
int bbSize = bb.limit() - bb.position();
|
||||
if (bbSize > maxExpansionSize)
|
||||
{
|
||||
LodUtil.assertNotReach("maxExpansionSize is [" + maxExpansionSize + "] but buffer size is [" + bbSize + "]!");
|
||||
}
|
||||
|
||||
// Don't upload an empty buffer
|
||||
if (bbSize == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure the buffer is ready for uploading
|
||||
this.createOrChangeBufferTypeForUpload(uploadMethod);
|
||||
|
||||
switch (uploadMethod)
|
||||
{
|
||||
//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!");
|
||||
}
|
||||
}
|
||||
/** Requires the buffer to be bound */
|
||||
protected void uploadBufferStorage(ByteBuffer bb, int bufferStorageHint)
|
||||
{
|
||||
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.bind();
|
||||
GL44.glBufferStorage(this.getBufferBindingTarget(), bb, 0);
|
||||
this.size = bbSize;
|
||||
}
|
||||
/** Requires the buffer to be bound */
|
||||
protected void uploadBufferData(ByteBuffer bb, int bufferDataHint)
|
||||
{
|
||||
LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use bufferData upload method!");
|
||||
|
||||
int bbSize = bb.limit() - bb.position();
|
||||
GL32.glBufferData(this.getBufferBindingTarget(), bb, bufferDataHint);
|
||||
this.size = bbSize;
|
||||
}
|
||||
/** Requires the buffer to be bound */
|
||||
protected void uploadSubData(ByteBuffer bb, int maxExpansionSize, int bufferDataHint)
|
||||
{
|
||||
LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use subData upload method!");
|
||||
|
||||
int bbSize = bb.limit() - bb.position();
|
||||
if (this.size < bbSize || this.size > bbSize * BUFFER_SHRINK_TRIGGER)
|
||||
{
|
||||
int newSize = (int) (bbSize * BUFFER_EXPANSION_MULTIPLIER);
|
||||
if (newSize > maxExpansionSize) newSize = maxExpansionSize;
|
||||
GL32.glBufferData(this.getBufferBindingTarget(), newSize, bufferDataHint);
|
||||
this.size = newSize;
|
||||
}
|
||||
GL32.glBufferSubData(this.getBufferBindingTarget(), 0, bb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// overrides //
|
||||
//===========//
|
||||
|
||||
@Override
|
||||
public void close() { this.destroyAsync(); }
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return (this.bufferStorage ? "" : "Static-") + this.getClass().getSimpleName() +
|
||||
"[id:" + this.id + ",size:" + this.size + (this.isMapped ? ",MAPPED" : "") + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* Makes sure the buffer exists and is of the correct format
|
||||
* before uploading.
|
||||
*/
|
||||
private void createOrChangeBufferTypeForUpload(EDhApiGpuUploadMethod uploadMethod)
|
||||
{
|
||||
// create/change the buffer type if necessary
|
||||
if (uploadMethod.useBufferStorage != this.bufferStorage)
|
||||
{
|
||||
// recreate if the buffer storage type changed
|
||||
this.bind();
|
||||
this.destroyAsync();
|
||||
this.create(uploadMethod.useBufferStorage);
|
||||
this.bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prevent uploading to the null buffer (ID 0).
|
||||
// This can happen if the buffer was deleted previously.
|
||||
if (this.id == 0)
|
||||
{
|
||||
this.create(this.bufferStorage);
|
||||
}
|
||||
|
||||
this.bind();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// static cleanup //
|
||||
//================//
|
||||
|
||||
private static void runPhantomReferenceCleanupLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(PHANTOM_REF_CHECK_TIME_IN_MS);
|
||||
}
|
||||
catch (InterruptedException ignore) { }
|
||||
|
||||
|
||||
Reference<? extends GLBuffer> phantomRef = PHANTOM_REFERENCE_QUEUE.poll();
|
||||
while (phantomRef != null)
|
||||
{
|
||||
// destroy the buffer if it hasn't been cleared yet
|
||||
if (PHANTOM_TO_BUFFER_ID.containsKey(phantomRef))
|
||||
{
|
||||
int id = PHANTOM_TO_BUFFER_ID.get(phantomRef);
|
||||
destroyBufferIdAsync(id);
|
||||
//LOGGER.warn("Buffer Phantom collected, ID: ["+id+"]");
|
||||
}
|
||||
|
||||
phantomRef = PHANTOM_REFERENCE_QUEUE.poll();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unexpected error in buffer cleanup thread: [" + e.getMessage() + "].", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.buffer;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* This is a container for a OpenGL
|
||||
* VBO (Vertex Buffer Object).
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class GLElementBuffer extends GLBuffer
|
||||
{
|
||||
/**
|
||||
* When uploading to a buffer that is too small, recreate it this many times
|
||||
* bigger than the upload payload
|
||||
*/
|
||||
protected int indicesCount = 0;
|
||||
public int getIndicesCount() { return this.indicesCount; }
|
||||
protected int type = GL32.GL_UNSIGNED_INT;
|
||||
public int getType() { return type; }
|
||||
|
||||
public GLElementBuffer(boolean isBufferStorage)
|
||||
{
|
||||
super(isBufferStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyAsync()
|
||||
{
|
||||
super.destroyAsync();
|
||||
this.indicesCount = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferBindingTarget()
|
||||
{
|
||||
return GL32.GL_ELEMENT_ARRAY_BUFFER;
|
||||
}
|
||||
|
||||
}
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
|
||||
/**
|
||||
* This is a container for a OpenGL
|
||||
* VBO (Vertex Buffer Object).
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class GLVertexBuffer extends GLBuffer
|
||||
{
|
||||
/**
|
||||
* When uploading to a buffer that is too small, recreate it this many times
|
||||
* bigger than the upload payload
|
||||
*/
|
||||
protected int vertexCount = 0;
|
||||
public int getVertexCount() { return this.vertexCount; }
|
||||
// FIXME: This setter is needed for premapping buffer to manually set the vertexCount. Fix this.
|
||||
public void setVertexCount(int vertexCount) { this.vertexCount = vertexCount; }
|
||||
|
||||
|
||||
public GLVertexBuffer(boolean isBufferStorage)
|
||||
{
|
||||
super(isBufferStorage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void destroyAsync()
|
||||
{
|
||||
super.destroyAsync();
|
||||
this.vertexCount = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferBindingTarget() { return GL32.GL_ARRAY_BUFFER; }
|
||||
|
||||
/**
|
||||
* bufferSize is the number of shared verticies. <br>
|
||||
* This number will be higher when actually rendered since each box's face needs 2 triangles
|
||||
* with 2 shared verticies.
|
||||
*/
|
||||
public void uploadBuffer(ByteBuffer byteBuffer, int bufferSize, EDhApiGpuUploadMethod uploadMethod, int maxExpensionSize)
|
||||
{
|
||||
if (bufferSize < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("VertCount is negative!");
|
||||
}
|
||||
|
||||
// If size is zero, just ignore it.
|
||||
if (byteBuffer.limit() - byteBuffer.position() != 0)
|
||||
{
|
||||
boolean useBuffStorage = uploadMethod.useBufferStorage;
|
||||
super.uploadBuffer(byteBuffer, uploadMethod, maxExpensionSize, useBuffStorage ? 0 : GL32.GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
// /4 to get the number of cubes
|
||||
// *6 to get the number of verticies (2 triangles, 3 verticies each)
|
||||
this.vertexCount = (bufferSize / 4) * 6;
|
||||
}
|
||||
|
||||
}
|
||||
-195
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.buffer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLEnums;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class QuadElementBuffer extends GLElementBuffer
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public QuadElementBuffer() { super(false); }
|
||||
|
||||
public void reserve(int quadCount)
|
||||
{
|
||||
if (quadCount < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("quadCount must be greater than 0");
|
||||
}
|
||||
if (quadCount == 0)
|
||||
{
|
||||
// shouldn't happen, but just in case
|
||||
return;
|
||||
}
|
||||
|
||||
this.indicesCount = quadCount * 6; // 2 triangles per quad
|
||||
if (this.indicesCount >= this.getCapacity()
|
||||
&& this.indicesCount < this.getCapacity() * BUFFER_SHRINK_TRIGGER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int vertexCount = quadCount * 4; // 4 vertices per quad
|
||||
|
||||
if (vertexCount < 255)
|
||||
{
|
||||
// Reserve 1 for the reset index
|
||||
this.type = GL32.GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (vertexCount < 65535)
|
||||
{
|
||||
// Reserve 1 for the reset index
|
||||
this.type = GL32.GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.type = GL32.GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(this.indicesCount * GLEnums.getTypeSize(this.type));
|
||||
buildBuffer(quadCount, buffer, this.type);
|
||||
this.bind();
|
||||
super.uploadBuffer(buffer, EDhApiGpuUploadMethod.DATA,
|
||||
this.indicesCount * GLEnums.getTypeSize(this.type), GL32.GL_STATIC_DRAW);
|
||||
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
public int getCapacity() { return super.getSize() / GLEnums.getTypeSize(this.getType()); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// building //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
private static void buildBuffer(int quadCount, ByteBuffer buffer, int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GL32.GL_UNSIGNED_BYTE:
|
||||
buildBufferByte(quadCount, buffer);
|
||||
break;
|
||||
case GL32.GL_UNSIGNED_SHORT:
|
||||
buildBufferShort(quadCount, buffer);
|
||||
break;
|
||||
case GL32.GL_UNSIGNED_INT:
|
||||
buildBufferInt(quadCount, buffer);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown buffer type: [" + type + "].");
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildBufferByte(int quadCount, ByteBuffer buffer)
|
||||
{
|
||||
for (int i = 0; i < quadCount; i++)
|
||||
{
|
||||
int vIndex = i * 4;
|
||||
// First triangle
|
||||
buffer.put((byte) (vIndex));
|
||||
buffer.put((byte) (vIndex + 1));
|
||||
buffer.put((byte) (vIndex + 2));
|
||||
// Second triangle
|
||||
buffer.put((byte) (vIndex + 2));
|
||||
buffer.put((byte) (vIndex + 3));
|
||||
buffer.put((byte) (vIndex));
|
||||
}
|
||||
if (buffer.hasRemaining())
|
||||
{
|
||||
throw new IllegalStateException("QuadElementBuffer is not full somehow after building");
|
||||
}
|
||||
buffer.rewind();
|
||||
}
|
||||
private static void buildBufferShort(int quadCount, ByteBuffer buffer)
|
||||
{
|
||||
for (int i = 0; i < quadCount; i++)
|
||||
{
|
||||
int vIndex = i * 4;
|
||||
// First triangle
|
||||
buffer.putShort((short) (vIndex));
|
||||
buffer.putShort((short) (vIndex + 1));
|
||||
buffer.putShort((short) (vIndex + 2));
|
||||
// Second triangle
|
||||
buffer.putShort((short) (vIndex + 2));
|
||||
buffer.putShort((short) (vIndex + 3));
|
||||
buffer.putShort((short) (vIndex));
|
||||
}
|
||||
if (buffer.hasRemaining())
|
||||
{
|
||||
throw new IllegalStateException("QuadElementBuffer is not full somehow after building");
|
||||
}
|
||||
buffer.rewind();
|
||||
}
|
||||
private static void buildBufferInt(int quadCount, ByteBuffer buffer)
|
||||
{
|
||||
for (int i = 0; i < quadCount; i++)
|
||||
{
|
||||
int vIndex = i * 4;
|
||||
// First triangle
|
||||
buffer.putInt(vIndex);
|
||||
buffer.putInt(vIndex + 1);
|
||||
buffer.putInt(vIndex + 2);
|
||||
// Second triangle
|
||||
buffer.putInt(vIndex + 2);
|
||||
buffer.putInt(vIndex + 3);
|
||||
buffer.putInt(vIndex);
|
||||
}
|
||||
if (buffer.hasRemaining())
|
||||
{
|
||||
throw new IllegalStateException("QuadElementBuffer is not full somehow after building");
|
||||
}
|
||||
buffer.rewind();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.shader;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL32C;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.lwjgl.system.NativeType;
|
||||
|
||||
/**
|
||||
* This object holds a OpenGL reference to a shader
|
||||
* and allows for reading in and compiling a shader file.
|
||||
*/
|
||||
public class Shader
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||
.build();
|
||||
|
||||
|
||||
/** OpenGL shader ID */
|
||||
public final int id;
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
/**
|
||||
* Creates a shader with specified type.
|
||||
*
|
||||
* @param type Either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
|
||||
* @param sourceString File path of the shader
|
||||
* @throws RuntimeException if the shader fails to compile
|
||||
*/
|
||||
public Shader(int type, String sourceString)
|
||||
{
|
||||
LOGGER.info("Loading shader with type: ["+type+"]");
|
||||
LOGGER.debug("Source: \n["+sourceString+"]");
|
||||
if (sourceString == null || sourceString.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("No shader source given.");
|
||||
}
|
||||
|
||||
// Create an empty shader object
|
||||
this.id = GL32.glCreateShader(type);
|
||||
if (this.id == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Failed to create shader with type ["+type+"] and Source: \n["+sourceString+"].");
|
||||
}
|
||||
|
||||
safeShaderSource(this.id, sourceString);
|
||||
GL32.glCompileShader(this.id);
|
||||
// check if the shader compiled
|
||||
int status = GL32.glGetShaderi(this.id, GL32.GL_COMPILE_STATUS);
|
||||
if (status != GL32.GL_TRUE)
|
||||
{
|
||||
|
||||
String message = "Shader compiler error. Details: [" + GL32.glGetShaderInfoLog(this.id) + "]\n";
|
||||
message += "Source: \n[" + sourceString + "]";
|
||||
this.free(); // important!
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
LOGGER.info("Shader loaded sucessfully.");
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// helpers //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
/**
|
||||
* Identical in function to {@link GL32C#glShaderSource(int, CharSequence)} but
|
||||
* passes a null pointer for string length to force the driver to rely on the null
|
||||
* terminator for string length. This is a workaround for an apparent flaw with some
|
||||
* AMD drivers that don't receive or interpret the length correctly, resulting in
|
||||
* an access violation when the driver tries to read past the string memory.
|
||||
*
|
||||
* <p>Hat tip to fewizz for the find and the fix.
|
||||
*
|
||||
* <p>Source: https://github.com/vram-guild/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
|
||||
*/
|
||||
private static void safeShaderSource(@NativeType("GLuint") int glId, @NativeType("GLchar const **") CharSequence source)
|
||||
{
|
||||
final MemoryStack stack = MemoryStack.stackGet();
|
||||
final int stackPointer = stack.getPointer();
|
||||
|
||||
try
|
||||
{
|
||||
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
|
||||
final PointerBuffer pointers = stack.mallocPointer(1);
|
||||
pointers.put(sourceBuffer);
|
||||
|
||||
GL32.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||
org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1);
|
||||
}
|
||||
finally
|
||||
{
|
||||
stack.setPointer(stackPointer);
|
||||
}
|
||||
}
|
||||
|
||||
public void free() { GL32.glDeleteShader(this.id); }
|
||||
|
||||
public static String loadFile(String path, boolean absoluteFilePath)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
// open the file
|
||||
InputStream in;
|
||||
if (absoluteFilePath)
|
||||
{
|
||||
// Throws FileNotFoundException
|
||||
in = new FileInputStream(path); // Note: this should use OS path seperator
|
||||
}
|
||||
else
|
||||
{
|
||||
in = Shader.class.getClassLoader().getResourceAsStream(path); // Note: path seperator should be '/'
|
||||
if (in == null)
|
||||
{
|
||||
throw new FileNotFoundException("Shader file not found in resource: " + path);
|
||||
}
|
||||
}
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
// read in the file
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
stringBuilder.append(line).append("\n");
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to load shader from file [" + path + "]. Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-230
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.shader;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
|
||||
|
||||
/**
|
||||
* This object holds the reference to a OpenGL shader program
|
||||
* and contains a few methods that can be used with OpenGL shader programs.
|
||||
* The reason for many of these simple wrapper methods is as reminders of what
|
||||
* can (and needs to be) done with a shader program.
|
||||
*/
|
||||
public class ShaderProgram
|
||||
{
|
||||
/** Stores the handle of the program. */
|
||||
public final int id;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public ShaderProgram(String vertResourcePath, String fragResourcePath, String attribute) { this(vertResourcePath, fragResourcePath, new String[]{ attribute }); }
|
||||
/**
|
||||
* @param vertResourcePath the relative path the vertex shader should be found
|
||||
* @param fragResourcePath the relative path the fragment shader should be found
|
||||
*/
|
||||
public ShaderProgram(String vertResourcePath, String fragResourcePath, String[] attributes)
|
||||
{
|
||||
this.id = GL32.glCreateProgram();
|
||||
|
||||
{
|
||||
String shaderString = Shader.loadFile(vertResourcePath, false);
|
||||
Shader vertShader = new Shader(GL32.GL_VERTEX_SHADER, shaderString);
|
||||
GL32.glAttachShader(this.id, vertShader.id);
|
||||
vertShader.free();
|
||||
}
|
||||
|
||||
{
|
||||
String shaderString = Shader.loadFile(fragResourcePath, false);
|
||||
Shader fragShader = new Shader(GL32.GL_FRAGMENT_SHADER, shaderString);
|
||||
GL32.glAttachShader(this.id, fragShader.id);
|
||||
fragShader.free();
|
||||
}
|
||||
|
||||
for (int i = 0; i < attributes.length; i++)
|
||||
{
|
||||
GL32.glBindAttribLocation(this.id, i, attributes[i]);
|
||||
}
|
||||
GL32.glLinkProgram(this.id);
|
||||
|
||||
int status = GL32.glGetProgrami(this.id, GL32.GL_LINK_STATUS);
|
||||
if (status != GL32.GL_TRUE)
|
||||
{
|
||||
String message = "Shader Link Error. Details: " + GL32.glGetProgramInfoLog(this.id);
|
||||
this.free(); // important!
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
GL32.glUseProgram(this.id); // This HAVE to be a direct call to prevent calling the overloaded version
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// binding //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
public void bind() { GL32.glUseProgram(this.id); }
|
||||
public void unbind() { GL32.glUseProgram(0); }
|
||||
|
||||
public void free() { GL32.glDeleteProgram(this.id); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//============//
|
||||
// attributes //
|
||||
//============//
|
||||
//region
|
||||
|
||||
/**
|
||||
* WARNING: Slow native call! Cache it if possible!
|
||||
* Gets the location of an attribute variable with specified name.
|
||||
* Calls GL20.glGetAttribLocation(id, name)
|
||||
*
|
||||
* @param name Attribute name
|
||||
* @return Location of the attribute
|
||||
* @throws RuntimeException if attribute not found
|
||||
*/
|
||||
public int getAttributeLocation(CharSequence name)
|
||||
{
|
||||
int i = GL32.glGetAttribLocation(id, name);
|
||||
if (i == -1) throw new RuntimeException("Attribute name not found: " + name);
|
||||
return i;
|
||||
}
|
||||
/**
|
||||
* Same as above but without throwing errors. <br>
|
||||
* Returns -1 if the attribute doesn't exist or has been optimized out.
|
||||
*/
|
||||
public int tryGetAttributeLocation(CharSequence name)
|
||||
{ return GL32.glGetAttribLocation(this.id, name); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// uniforms //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
/**
|
||||
* WARNING: Slow native call! Cache it if possible!
|
||||
* Gets the location of a uniform variable with specified name.
|
||||
* Calls GL20.glGetUniformLocation(id, name)
|
||||
*
|
||||
* @param name Uniform name
|
||||
* @return Location of the Uniform
|
||||
* @throws RuntimeException if uniform not found
|
||||
*/
|
||||
public int getUniformLocation(CharSequence name) throws RuntimeException
|
||||
{
|
||||
int i = GL32.glGetUniformLocation(id, name);
|
||||
if (i == -1)
|
||||
{
|
||||
throw new RuntimeException("Uniform name not found: " + name);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Same as above but without throwing errors.
|
||||
// Return -1 if uniform doesn't exist or has been optimized out
|
||||
public int tryGetUniformLocation(CharSequence name)
|
||||
{ return GL32.glGetUniformLocation(this.id, name); }
|
||||
|
||||
/** Requires a bound ShaderProgram. */
|
||||
public void setUniform(int location, boolean value) { GL32.glUniform1i(location, value ? 1 : 0); }
|
||||
/** @see ShaderProgram#setUniform(int, boolean) */
|
||||
public void trySetUniform(int location, boolean value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
/** Requires a bound ShaderProgram. */
|
||||
public void setUniform(int location, int value) { GL32.glUniform1i(location, value); }
|
||||
/** @see ShaderProgram#setUniform(int, int) */
|
||||
public void trySetUniform(int location, int value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
/** Requires a bound ShaderProgram. */
|
||||
public void setUniform(int location, float value) { GL32.glUniform1f(location, value); }
|
||||
/** @see ShaderProgram#setUniform(int, float) */
|
||||
public void trySetUniform(int location, float value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
/** Requires a bound ShaderProgram. */
|
||||
public void setUniform(int location, Vec3f value) { GL32.glUniform3f(location, value.x, value.y, value.z); }
|
||||
/** @see ShaderProgram#setUniform(int, Vec3f) */
|
||||
public void trySetUniform(int location, Vec3f value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
/** Requires a bound ShaderProgram. */
|
||||
public void setUniform(int location, DhApiVec3i value) { GL32.glUniform3i(location, value.x, value.y, value.z); }
|
||||
/** @see ShaderProgram#setUniform(int, Mat4f) */
|
||||
public void trySetUniform(int location, DhApiVec3i value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
/** Requires a bound ShaderProgram. */
|
||||
public void setUniform(int location, Mat4f value)
|
||||
{
|
||||
try (MemoryStack stack = MemoryStack.stackPush())
|
||||
{
|
||||
FloatBuffer buffer = stack.mallocFloat(4 * 4);
|
||||
value.store(buffer);
|
||||
GL32.glUniformMatrix4fv(location, false, buffer);
|
||||
}
|
||||
}
|
||||
/** @see ShaderProgram#setUniform(int, Mat4f) */
|
||||
public void trySetUniform(int location, Mat4f value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
/**
|
||||
* Converts the color's RGBA values into values between 0 and 1. <br>
|
||||
* Requires a bound ShaderProgram.
|
||||
*/
|
||||
public void setUniform(int location, Color value)
|
||||
{
|
||||
GL32.glUniform4f(location,
|
||||
value.getRed() / 256.0f,
|
||||
value.getGreen() / 256.0f,
|
||||
value.getBlue() / 256.0f,
|
||||
value.getAlpha() / 256.0f);
|
||||
}
|
||||
/** @see ShaderProgram#setUniform(int, Color) */
|
||||
public void trySetUniform(int location, Color value) { if (location != -1) { this.setUniform(location, value); } }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import org.lwjgl.opengl.GL11C;
|
||||
import org.lwjgl.opengl.GL13C;
|
||||
import org.lwjgl.opengl.GL43C;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class DHDepthTexture
|
||||
{
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private int id;
|
||||
public DHDepthTexture(int width, int height, EDhDepthBufferFormat format)
|
||||
{
|
||||
this.id = GL43C.glGenTextures();
|
||||
|
||||
this.resize(width, height, format);
|
||||
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MIN_FILTER, GL11C.GL_NEAREST);
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, GL11C.GL_NEAREST);
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
|
||||
|
||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// For internal use by Iris for copying data. Do not use this in DH.
|
||||
public DHDepthTexture(int id) { this.id = id; }
|
||||
|
||||
public void resize(int width, int height, EDhDepthBufferFormat format)
|
||||
{
|
||||
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, this.getTextureId());
|
||||
GL43C.glTexImage2D(GL11C.GL_TEXTURE_2D, 0, format.getGlInternalFormat(), width, height, 0,
|
||||
format.getGlType(), format.getGlFormat(), (ByteBuffer) null);
|
||||
}
|
||||
|
||||
public int getTextureId()
|
||||
{
|
||||
if (this.id == -1)
|
||||
{
|
||||
throw new IllegalStateException("Depth texture does not exist!");
|
||||
}
|
||||
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void destroy()
|
||||
{
|
||||
GLMC.glDeleteTextures(this.getTextureId());
|
||||
this.id = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-184
@@ -1,184 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import org.joml.Vector2i;
|
||||
import org.lwjgl.opengl.GL11C;
|
||||
import org.lwjgl.opengl.GL13C;
|
||||
import org.lwjgl.opengl.GL43C;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class DhColorTexture
|
||||
{
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private final EDhInternalTextureFormat internalFormat;
|
||||
private final EDhPixelFormat format;
|
||||
private final EDhPixelType type;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
private boolean isValid;
|
||||
/** AKA, the OpenGL name of this texture */
|
||||
private final int id;
|
||||
|
||||
private static final ByteBuffer NULL_BUFFER = null;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public DhColorTexture(Builder builder)
|
||||
{
|
||||
this.isValid = true;
|
||||
|
||||
this.internalFormat = builder.internalFormat;
|
||||
this.format = builder.format;
|
||||
this.type = builder.type;
|
||||
|
||||
this.width = builder.width;
|
||||
this.height = builder.height;
|
||||
|
||||
this.id = GL43C.glGenTextures();
|
||||
|
||||
boolean isPixelFormatInteger = builder.internalFormat.getPixelFormat().isInteger();
|
||||
this.setupTexture(this.id, builder.width, builder.height, !isPixelFormatInteger); // this binds the texture
|
||||
|
||||
// Clean up after ourselves
|
||||
// This is strictly defensive to ensure that other buggy code doesn't tamper with our textures
|
||||
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
private void setupTexture(int id, int width, int height, boolean allowsLinear)
|
||||
{
|
||||
this.resizeTexture(id, width, height);
|
||||
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MIN_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
|
||||
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
|
||||
|
||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
|
||||
private void resizeTexture(int texture, int width, int height)
|
||||
{
|
||||
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, texture);
|
||||
GL43C.glTexImage2D(GL11C.GL_TEXTURE_2D, 0, this.internalFormat.getGlFormat(), width, height, 0, this.format.getGlFormat(), this.type.getGlFormat(), NULL_BUFFER);
|
||||
}
|
||||
|
||||
void resize(Vector2i textureScaleOverride) { this.resize(textureScaleOverride.x, textureScaleOverride.y); }
|
||||
|
||||
// Package private, call CompositeRenderTargets#resizeIfNeeded instead.
|
||||
public void resize(int width, int height)
|
||||
{
|
||||
this.throwIfInvalid();
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.resizeTexture(this.id, width, height);
|
||||
}
|
||||
|
||||
public EDhInternalTextureFormat getInternalFormat() { return this.internalFormat; }
|
||||
|
||||
public int getTextureId()
|
||||
{
|
||||
this.throwIfInvalid();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public int getWidth() { return this.width; }
|
||||
|
||||
public int getHeight() { return this.height; }
|
||||
|
||||
public void destroy()
|
||||
{
|
||||
this.throwIfInvalid();
|
||||
this.isValid = false;
|
||||
|
||||
GLMC.glDeleteTextures(this.id);
|
||||
}
|
||||
|
||||
/** @throws IllegalStateException if the texture isn't valid */
|
||||
private void throwIfInvalid()
|
||||
{
|
||||
if (!this.isValid)
|
||||
{
|
||||
throw new IllegalStateException("Attempted to use a deleted composite render target");
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder builder() { return new Builder(); }
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
private EDhInternalTextureFormat internalFormat = EDhInternalTextureFormat.RGBA8;
|
||||
private int width = 0;
|
||||
private int height = 0;
|
||||
private EDhPixelFormat format = EDhPixelFormat.RGBA;
|
||||
private EDhPixelType type = EDhPixelType.UNSIGNED_BYTE;
|
||||
|
||||
private Builder()
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
public Builder setInternalFormat(EDhInternalTextureFormat format)
|
||||
{
|
||||
this.internalFormat = format;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDimensions(int width, int height)
|
||||
{
|
||||
if (width <= 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Width must be greater than zero");
|
||||
}
|
||||
|
||||
if (height <= 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Height must be greater than zero");
|
||||
}
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPixelFormat(EDhPixelFormat pixelFormat)
|
||||
{
|
||||
this.format = pixelFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPixelType(EDhPixelType pixelType)
|
||||
{
|
||||
this.type = pixelType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DhColorTexture build() { return new DhColorTexture(this); }
|
||||
|
||||
}
|
||||
}
|
||||
-153
@@ -1,153 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class DhFramebuffer implements IDhApiFramebuffer
|
||||
{
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
private final Int2IntMap attachments;
|
||||
private final int maxDrawBuffers;
|
||||
private final int maxColorAttachments;
|
||||
private boolean hasDepthAttachment;
|
||||
private int id;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public DhFramebuffer()
|
||||
{
|
||||
this.id = GL32.glGenFramebuffers();
|
||||
|
||||
this.attachments = new Int2IntArrayMap();
|
||||
this.maxDrawBuffers = GL32.glGetInteger(GL32.GL_MAX_DRAW_BUFFERS);
|
||||
this.maxColorAttachments = GL32.glGetInteger(GL32.GL_MAX_COLOR_ATTACHMENTS);
|
||||
this.hasDepthAttachment = false;
|
||||
}
|
||||
|
||||
/** For internal use by Iris, do not remove. */
|
||||
public DhFramebuffer(int id)
|
||||
{
|
||||
this.id = id;
|
||||
|
||||
this.attachments = new Int2IntArrayMap();
|
||||
this.maxDrawBuffers = GL32.glGetInteger(GL32.GL_MAX_DRAW_BUFFERS);
|
||||
this.maxColorAttachments = GL32.glGetInteger(GL32.GL_MAX_COLOR_ATTACHMENTS);
|
||||
this.hasDepthAttachment = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public void addDepthAttachment(int textureId, boolean isCombinedStencil)
|
||||
{
|
||||
this.bind();
|
||||
|
||||
int depthAttachment = isCombinedStencil ? GL32.GL_DEPTH_STENCIL_ATTACHMENT : GL32.GL_DEPTH_ATTACHMENT;
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, depthAttachment, GL32.GL_TEXTURE_2D, textureId, 0);
|
||||
|
||||
this.hasDepthAttachment = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColorAttachment(int textureIndex, int textureId)
|
||||
{
|
||||
this.bind();
|
||||
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0 + textureIndex, GL32.GL_TEXTURE_2D, textureId, 0);
|
||||
this.attachments.put(textureIndex, textureId);
|
||||
}
|
||||
|
||||
public void noDrawBuffers()
|
||||
{
|
||||
this.bind();
|
||||
GL32.glDrawBuffers(new int[]{GL32.GL_NONE});
|
||||
}
|
||||
|
||||
public void drawBuffers(int[] buffers)
|
||||
{
|
||||
int[] glBuffers = new int[buffers.length];
|
||||
int index = 0;
|
||||
|
||||
if (buffers.length > this.maxDrawBuffers)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot write to more than " + this.maxDrawBuffers + " draw buffers on this GPU");
|
||||
}
|
||||
|
||||
for (int buffer : buffers)
|
||||
{
|
||||
if (buffer >= this.maxColorAttachments)
|
||||
{
|
||||
throw new IllegalArgumentException("Only " + this.maxColorAttachments + " color attachments are supported on this GPU, but an attempt was made to write to a color attachment with index " + buffer);
|
||||
}
|
||||
|
||||
glBuffers[index++] = GL32.GL_COLOR_ATTACHMENT0 + buffer;
|
||||
}
|
||||
|
||||
this.bind();
|
||||
GL32.glDrawBuffers(new int[]{GL32.GL_NONE});
|
||||
}
|
||||
|
||||
public void readBuffer(int buffer)
|
||||
{
|
||||
this.bind();
|
||||
GL32.glReadBuffer(GL32.GL_COLOR_ATTACHMENT0 + buffer);
|
||||
}
|
||||
|
||||
public int getColorAttachment(int index) { return this.attachments.get(index); }
|
||||
|
||||
public boolean hasDepthAttachment() { return this.hasDepthAttachment; }
|
||||
|
||||
@Override
|
||||
public void bind()
|
||||
{
|
||||
if (this.id == -1)
|
||||
{
|
||||
throw new IllegalStateException("Framebuffer does not exist!");
|
||||
}
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.id);
|
||||
}
|
||||
|
||||
public void bindAsReadBuffer() { GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, this.id); }
|
||||
|
||||
public void bindAsDrawBuffer() { GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, this.id); }
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.id);
|
||||
this.id = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus()
|
||||
{
|
||||
this.bind();
|
||||
int status = GL32.glCheckFramebufferStatus(GL32.GL_FRAMEBUFFER);
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() { return this.id; }
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// API methods //
|
||||
//=============//
|
||||
|
||||
public boolean overrideThisFrame() { return true; }
|
||||
|
||||
}
|
||||
-114
@@ -1,114 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.opengl.GL30C;
|
||||
import org.lwjgl.opengl.GL43C;
|
||||
|
||||
public enum EDhDepthBufferFormat
|
||||
{
|
||||
DEPTH(false),
|
||||
DEPTH16(false),
|
||||
DEPTH24(false),
|
||||
DEPTH32(false),
|
||||
DEPTH32F(false),
|
||||
DEPTH_STENCIL(true),
|
||||
DEPTH24_STENCIL8(true),
|
||||
DEPTH32F_STENCIL8(true);
|
||||
|
||||
|
||||
|
||||
private final boolean combinedStencil;
|
||||
|
||||
EDhDepthBufferFormat(boolean combinedStencil) { this.combinedStencil = combinedStencil; }
|
||||
|
||||
|
||||
|
||||
@Nullable
|
||||
public static EDhDepthBufferFormat fromGlEnum(int glenum)
|
||||
{
|
||||
switch (glenum)
|
||||
{
|
||||
case GL30C.GL_DEPTH_COMPONENT:
|
||||
return EDhDepthBufferFormat.DEPTH;
|
||||
case GL30C.GL_DEPTH_COMPONENT16:
|
||||
return EDhDepthBufferFormat.DEPTH16;
|
||||
case GL30C.GL_DEPTH_COMPONENT24:
|
||||
return EDhDepthBufferFormat.DEPTH24;
|
||||
case GL30C.GL_DEPTH_COMPONENT32:
|
||||
return EDhDepthBufferFormat.DEPTH32;
|
||||
case GL30C.GL_DEPTH_COMPONENT32F:
|
||||
return EDhDepthBufferFormat.DEPTH32F;
|
||||
case GL30C.GL_DEPTH_STENCIL:
|
||||
return EDhDepthBufferFormat.DEPTH_STENCIL;
|
||||
case GL30C.GL_DEPTH24_STENCIL8:
|
||||
return EDhDepthBufferFormat.DEPTH24_STENCIL8;
|
||||
case GL30C.GL_DEPTH32F_STENCIL8:
|
||||
return EDhDepthBufferFormat.DEPTH32F_STENCIL8;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static EDhDepthBufferFormat fromGlEnumOrDefault(int glenum)
|
||||
{
|
||||
EDhDepthBufferFormat format = fromGlEnum(glenum);
|
||||
if (format == null)
|
||||
{
|
||||
// yolo, just assume it's GL_DEPTH_COMPONENT
|
||||
return EDhDepthBufferFormat.DEPTH;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
public int getGlInternalFormat()
|
||||
{
|
||||
switch (this)
|
||||
{
|
||||
case DEPTH:
|
||||
return GL30C.GL_DEPTH_COMPONENT;
|
||||
case DEPTH16:
|
||||
return GL30C.GL_DEPTH_COMPONENT16;
|
||||
case DEPTH24:
|
||||
return GL30C.GL_DEPTH_COMPONENT24;
|
||||
case DEPTH32:
|
||||
return GL30C.GL_DEPTH_COMPONENT32;
|
||||
case DEPTH32F:
|
||||
return GL30C.GL_DEPTH_COMPONENT32F;
|
||||
case DEPTH_STENCIL:
|
||||
return GL30C.GL_DEPTH_STENCIL;
|
||||
case DEPTH24_STENCIL8:
|
||||
return GL30C.GL_DEPTH24_STENCIL8;
|
||||
case DEPTH32F_STENCIL8:
|
||||
return GL30C.GL_DEPTH32F_STENCIL8;
|
||||
}
|
||||
|
||||
throw new AssertionError("unreachable");
|
||||
}
|
||||
|
||||
public int getGlType() { return isCombinedStencil() ? GL30C.GL_DEPTH_STENCIL : GL30C.GL_DEPTH_COMPONENT; }
|
||||
|
||||
public int getGlFormat()
|
||||
{
|
||||
switch (this)
|
||||
{
|
||||
case DEPTH:
|
||||
case DEPTH16:
|
||||
return GL43C.GL_UNSIGNED_SHORT;
|
||||
case DEPTH24:
|
||||
case DEPTH32:
|
||||
return GL43C.GL_UNSIGNED_INT;
|
||||
case DEPTH32F:
|
||||
return GL30C.GL_FLOAT;
|
||||
case DEPTH_STENCIL:
|
||||
case DEPTH24_STENCIL8:
|
||||
return GL30C.GL_UNSIGNED_INT_24_8;
|
||||
case DEPTH32F_STENCIL8:
|
||||
return GL30C.GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
|
||||
}
|
||||
|
||||
throw new AssertionError("unreachable");
|
||||
}
|
||||
|
||||
public boolean isCombinedStencil() { return combinedStencil; }
|
||||
|
||||
}
|
||||
-130
@@ -1,130 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import org.lwjgl.opengl.GL11C;
|
||||
import org.lwjgl.opengl.GL30C;
|
||||
import org.lwjgl.opengl.GL31C;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum EDhInternalTextureFormat
|
||||
{
|
||||
RGBA(GL11C.GL_RGBA, EGlVersion.GL_11, EDhPixelFormat.RGBA),
|
||||
|
||||
// 8-bit normalized
|
||||
R8(GL30C.GL_R8, EGlVersion.GL_30, EDhPixelFormat.RED),
|
||||
RG8(GL30C.GL_RG8, EGlVersion.GL_30, EDhPixelFormat.RG),
|
||||
RGB8(GL11C.GL_RGB8, EGlVersion.GL_11, EDhPixelFormat.RGB),
|
||||
RGBA8(GL11C.GL_RGBA8, EGlVersion.GL_11, EDhPixelFormat.RGBA),
|
||||
|
||||
// 8-bit signed normalized
|
||||
R8_SNORM(GL31C.GL_R8_SNORM, EGlVersion.GL_31, EDhPixelFormat.RED),
|
||||
RG8_SNORM(GL31C.GL_RG8_SNORM, EGlVersion.GL_31, EDhPixelFormat.RG),
|
||||
RGB8_SNORM(GL31C.GL_RGB8_SNORM, EGlVersion.GL_31, EDhPixelFormat.RGB),
|
||||
RGBA8_SNORM(GL31C.GL_RGBA8_SNORM, EGlVersion.GL_31, EDhPixelFormat.RGBA),
|
||||
|
||||
// 16-bit normalized
|
||||
R16(GL30C.GL_R16, EGlVersion.GL_30, EDhPixelFormat.RED),
|
||||
RG16(GL30C.GL_RG16, EGlVersion.GL_30, EDhPixelFormat.RG),
|
||||
RGB16(GL11C.GL_RGB16, EGlVersion.GL_11, EDhPixelFormat.RGB),
|
||||
RGBA16(GL11C.GL_RGBA16, EGlVersion.GL_11, EDhPixelFormat.RGBA),
|
||||
|
||||
// 16-bit signed normalized
|
||||
R16_SNORM(GL31C.GL_R16_SNORM, EGlVersion.GL_31, EDhPixelFormat.RED),
|
||||
RG16_SNORM(GL31C.GL_RG16_SNORM, EGlVersion.GL_31, EDhPixelFormat.RG),
|
||||
RGB16_SNORM(GL31C.GL_RGB16_SNORM, EGlVersion.GL_31, EDhPixelFormat.RGB),
|
||||
RGBA16_SNORM(GL31C.GL_RGBA16_SNORM, EGlVersion.GL_31, EDhPixelFormat.RGBA),
|
||||
|
||||
// 16-bit float
|
||||
R16F(GL30C.GL_R16F, EGlVersion.GL_30, EDhPixelFormat.RED),
|
||||
RG16F(GL30C.GL_RG16F, EGlVersion.GL_30, EDhPixelFormat.RG),
|
||||
RGB16F(GL30C.GL_RGB16F, EGlVersion.GL_30, EDhPixelFormat.RGB),
|
||||
RGBA16F(GL30C.GL_RGBA16F, EGlVersion.GL_30, EDhPixelFormat.RGBA),
|
||||
|
||||
// 32-bit float
|
||||
R32F(GL30C.GL_R32F, EGlVersion.GL_30, EDhPixelFormat.RED),
|
||||
RG32F(GL30C.GL_RG32F, EGlVersion.GL_30, EDhPixelFormat.RG),
|
||||
RGB32F(GL30C.GL_RGB32F, EGlVersion.GL_30, EDhPixelFormat.RGB),
|
||||
RGBA32F(GL30C.GL_RGBA32F, EGlVersion.GL_30, EDhPixelFormat.RGBA),
|
||||
|
||||
// 8-bit integer
|
||||
R8I(GL30C.GL_R8I, EGlVersion.GL_30, EDhPixelFormat.RED_INTEGER),
|
||||
RG8I(GL30C.GL_RG8I, EGlVersion.GL_30, EDhPixelFormat.RG_INTEGER),
|
||||
RGB8I(GL30C.GL_RGB8I, EGlVersion.GL_30, EDhPixelFormat.RGB_INTEGER),
|
||||
RGBA8I(GL30C.GL_RGBA8I, EGlVersion.GL_30, EDhPixelFormat.RGBA_INTEGER),
|
||||
|
||||
// 8-bit unsigned integer
|
||||
R8UI(GL30C.GL_R8UI, EGlVersion.GL_30, EDhPixelFormat.RED_INTEGER),
|
||||
RG8UI(GL30C.GL_RG8UI, EGlVersion.GL_30, EDhPixelFormat.RG_INTEGER),
|
||||
RGB8UI(GL30C.GL_RGB8UI, EGlVersion.GL_30, EDhPixelFormat.RGB_INTEGER),
|
||||
RGBA8UI(GL30C.GL_RGBA8UI, EGlVersion.GL_30, EDhPixelFormat.RGBA_INTEGER),
|
||||
|
||||
// 16-bit integer
|
||||
R16I(GL30C.GL_R16I, EGlVersion.GL_30, EDhPixelFormat.RED_INTEGER),
|
||||
RG16I(GL30C.GL_RG16I, EGlVersion.GL_30, EDhPixelFormat.RG_INTEGER),
|
||||
RGB16I(GL30C.GL_RGB16I, EGlVersion.GL_30, EDhPixelFormat.RGB_INTEGER),
|
||||
RGBA16I(GL30C.GL_RGBA16I, EGlVersion.GL_30, EDhPixelFormat.RGBA_INTEGER),
|
||||
|
||||
// 16-bit unsigned integer
|
||||
R16UI(GL30C.GL_R16UI, EGlVersion.GL_30, EDhPixelFormat.RED_INTEGER),
|
||||
RG16UI(GL30C.GL_RG16UI, EGlVersion.GL_30, EDhPixelFormat.RG_INTEGER),
|
||||
RGB16UI(GL30C.GL_RGB16UI, EGlVersion.GL_30, EDhPixelFormat.RGB_INTEGER),
|
||||
RGBA16UI(GL30C.GL_RGBA16UI, EGlVersion.GL_30, EDhPixelFormat.RGBA_INTEGER),
|
||||
|
||||
// 32-bit integer
|
||||
R32I(GL30C.GL_R32I, EGlVersion.GL_30, EDhPixelFormat.RED_INTEGER),
|
||||
RG32I(GL30C.GL_RG32I, EGlVersion.GL_30, EDhPixelFormat.RG_INTEGER),
|
||||
RGB32I(GL30C.GL_RGB32I, EGlVersion.GL_30, EDhPixelFormat.RGB_INTEGER),
|
||||
RGBA32I(GL30C.GL_RGBA32I, EGlVersion.GL_30, EDhPixelFormat.RGBA_INTEGER),
|
||||
|
||||
// 32-bit unsigned integer
|
||||
R32UI(GL30C.GL_R32UI, EGlVersion.GL_30, EDhPixelFormat.RED_INTEGER),
|
||||
RG32UI(GL30C.GL_RG32UI, EGlVersion.GL_30, EDhPixelFormat.RG_INTEGER),
|
||||
RGB32UI(GL30C.GL_RGB32UI, EGlVersion.GL_30, EDhPixelFormat.RGB_INTEGER),
|
||||
RGBA32UI(GL30C.GL_RGBA32UI, EGlVersion.GL_30, EDhPixelFormat.RGBA_INTEGER),
|
||||
|
||||
// Mixed
|
||||
R3_G3_B2(GL11C.GL_R3_G3_B2, EGlVersion.GL_11, EDhPixelFormat.RGB),
|
||||
RGB5_A1(GL11C.GL_RGB5_A1, EGlVersion.GL_11, EDhPixelFormat.RGBA),
|
||||
RGB10_A2(GL11C.GL_RGB10_A2, EGlVersion.GL_11, EDhPixelFormat.RGBA),
|
||||
R11F_G11F_B10F(GL30C.GL_R11F_G11F_B10F, EGlVersion.GL_30, EDhPixelFormat.RGB),
|
||||
RGB9_E5(GL30C.GL_RGB9_E5, EGlVersion.GL_30, EDhPixelFormat.RGB);
|
||||
|
||||
|
||||
|
||||
private final int glFormat;
|
||||
private final EGlVersion minimumGlVersion;
|
||||
private final EDhPixelFormat expectedPixelFormat;
|
||||
|
||||
|
||||
|
||||
EDhInternalTextureFormat(int glFormat, EGlVersion minimumGlVersion, EDhPixelFormat expectedPixelFormat)
|
||||
{
|
||||
this.glFormat = glFormat;
|
||||
this.minimumGlVersion = minimumGlVersion;
|
||||
this.expectedPixelFormat = expectedPixelFormat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Optional<EDhInternalTextureFormat> fromString(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Optional.of(EDhInternalTextureFormat.valueOf(name.toUpperCase(Locale.US)));
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public int getGlFormat() { return this.glFormat; }
|
||||
|
||||
public EDhPixelFormat getPixelFormat() { return this.expectedPixelFormat; }
|
||||
|
||||
public EGlVersion getMinimumGlVersion() { return this.minimumGlVersion; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import org.lwjgl.opengl.GL11C;
|
||||
import org.lwjgl.opengl.GL12C;
|
||||
import org.lwjgl.opengl.GL30C;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum EDhPixelFormat
|
||||
{
|
||||
RED(GL11C.GL_RED, EGlVersion.GL_11, false),
|
||||
RG(GL30C.GL_RG, EGlVersion.GL_30, false),
|
||||
RGB(GL11C.GL_RGB, EGlVersion.GL_11, false),
|
||||
BGR(GL12C.GL_BGR, EGlVersion.GL_12, false),
|
||||
RGBA(GL11C.GL_RGBA, EGlVersion.GL_11, false),
|
||||
BGRA(GL12C.GL_BGRA, EGlVersion.GL_12, false),
|
||||
RED_INTEGER(GL30C.GL_RED_INTEGER, EGlVersion.GL_30, true),
|
||||
RG_INTEGER(GL30C.GL_RG_INTEGER, EGlVersion.GL_30, true),
|
||||
RGB_INTEGER(GL30C.GL_RGB_INTEGER, EGlVersion.GL_30, true),
|
||||
BGR_INTEGER(GL30C.GL_BGR_INTEGER, EGlVersion.GL_30, true),
|
||||
RGBA_INTEGER(GL30C.GL_RGBA_INTEGER, EGlVersion.GL_30, true),
|
||||
BGRA_INTEGER(GL30C.GL_BGRA_INTEGER, EGlVersion.GL_30, true);
|
||||
|
||||
|
||||
|
||||
private final int glFormat;
|
||||
private final EGlVersion minimumGlVersion;
|
||||
private final boolean isInteger;
|
||||
|
||||
|
||||
|
||||
EDhPixelFormat(int glFormat, EGlVersion minimumGlVersion, boolean isInteger)
|
||||
{
|
||||
this.glFormat = glFormat;
|
||||
this.minimumGlVersion = minimumGlVersion;
|
||||
this.isInteger = isInteger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Optional<EDhPixelFormat> fromString(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Optional.of(EDhPixelFormat.valueOf(name.toUpperCase(Locale.US)));
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public int getGlFormat() { return this.glFormat; }
|
||||
|
||||
public EGlVersion getMinimumGlVersion() { return this.minimumGlVersion; }
|
||||
|
||||
public boolean isInteger() { return this.isInteger; }
|
||||
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
import org.lwjgl.opengl.GL11C;
|
||||
import org.lwjgl.opengl.GL12C;
|
||||
import org.lwjgl.opengl.GL30C;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum EDhPixelType
|
||||
{
|
||||
BYTE(GL11C.GL_BYTE, EGlVersion.GL_11),
|
||||
SHORT(GL11C.GL_SHORT, EGlVersion.GL_11),
|
||||
INT(GL11C.GL_INT, EGlVersion.GL_11),
|
||||
HALF_FLOAT(GL30C.GL_HALF_FLOAT, EGlVersion.GL_30),
|
||||
FLOAT(GL11C.GL_FLOAT, EGlVersion.GL_11),
|
||||
UNSIGNED_BYTE(GL11C.GL_UNSIGNED_BYTE, EGlVersion.GL_11),
|
||||
UNSIGNED_BYTE_3_3_2(GL12C.GL_UNSIGNED_BYTE_3_3_2, EGlVersion.GL_12),
|
||||
UNSIGNED_BYTE_2_3_3_REV(GL12C.GL_UNSIGNED_BYTE_2_3_3_REV, EGlVersion.GL_12),
|
||||
UNSIGNED_SHORT(GL11C.GL_UNSIGNED_SHORT, EGlVersion.GL_11),
|
||||
UNSIGNED_SHORT_5_6_5(GL12C.GL_UNSIGNED_SHORT_5_6_5, EGlVersion.GL_12),
|
||||
UNSIGNED_SHORT_5_6_5_REV(GL12C.GL_UNSIGNED_SHORT_5_6_5_REV, EGlVersion.GL_12),
|
||||
UNSIGNED_SHORT_4_4_4_4(GL12C.GL_UNSIGNED_SHORT_4_4_4_4, EGlVersion.GL_12),
|
||||
UNSIGNED_SHORT_4_4_4_4_REV(GL12C.GL_UNSIGNED_SHORT_4_4_4_4_REV, EGlVersion.GL_12),
|
||||
UNSIGNED_SHORT_5_5_5_1(GL12C.GL_UNSIGNED_SHORT_5_5_5_1, EGlVersion.GL_12),
|
||||
UNSIGNED_SHORT_1_5_5_5_REV(GL12C.GL_UNSIGNED_SHORT_1_5_5_5_REV, EGlVersion.GL_12),
|
||||
UNSIGNED_INT(GL11C.GL_UNSIGNED_INT, EGlVersion.GL_11),
|
||||
UNSIGNED_INT_8_8_8_8(GL12C.GL_UNSIGNED_INT_8_8_8_8, EGlVersion.GL_12),
|
||||
UNSIGNED_INT_8_8_8_8_REV(GL12C.GL_UNSIGNED_INT_8_8_8_8_REV, EGlVersion.GL_12),
|
||||
UNSIGNED_INT_10_10_10_2(GL12C.GL_UNSIGNED_INT_10_10_10_2, EGlVersion.GL_12),
|
||||
UNSIGNED_INT_2_10_10_10_REV(GL12C.GL_UNSIGNED_INT_2_10_10_10_REV, EGlVersion.GL_12);
|
||||
|
||||
|
||||
|
||||
private final int glFormat;
|
||||
private final EGlVersion minimumGlVersion;
|
||||
|
||||
|
||||
|
||||
EDhPixelType(int glFormat, EGlVersion minimumGlVersion)
|
||||
{
|
||||
this.glFormat = glFormat;
|
||||
this.minimumGlVersion = minimumGlVersion;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Optional<EDhPixelType> fromString(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Optional.of(EDhPixelType.valueOf(name.toUpperCase(Locale.US)));
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public int getGlFormat() { return glFormat; }
|
||||
|
||||
public EGlVersion getMinimumGlVersion() { return minimumGlVersion; }
|
||||
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.texture;
|
||||
|
||||
public enum EGlVersion
|
||||
{
|
||||
GL_11,
|
||||
GL_12,
|
||||
GL_30,
|
||||
GL_31
|
||||
}
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.vertexAttribute;
|
||||
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Base for binding/unbinding Vertex Attribute objects (VAO's).
|
||||
*
|
||||
* @see VertexAttributePostGL43
|
||||
* @see VertexAttributePreGL43
|
||||
*/
|
||||
public abstract class AbstractVertexAttribute
|
||||
{
|
||||
/** Stores the handle of the AbstractVertexAttribute. */
|
||||
public final int id;
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
// This will bind AbstractVertexAttribute
|
||||
protected AbstractVertexAttribute()
|
||||
{
|
||||
this.id = GL32.glGenVertexArrays();
|
||||
GL32.glBindVertexArray(this.id);
|
||||
}
|
||||
|
||||
public static AbstractVertexAttribute create()
|
||||
{
|
||||
if (GLProxy.getInstance().vertexAttributeBufferBindingSupported)
|
||||
{
|
||||
return new VertexAttributePostGL43();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new VertexAttributePreGL43();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// binding //
|
||||
//=========//
|
||||
|
||||
public void bind() { GL32.glBindVertexArray(this.id); }
|
||||
public void unbind() { GL32.glBindVertexArray(0); }
|
||||
|
||||
/** Always remember to always free your resources! */
|
||||
public void free() { GL32.glDeleteVertexArrays(this.id); }
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// abstract methods //
|
||||
//==================//
|
||||
|
||||
/** Requires both AbstractVertexAttribute and VertexBuffer to be bound */
|
||||
public abstract void bindBufferToAllBindingPoints(int buffer);
|
||||
/** Requires both AbstractVertexAttribute and VertexBuffer to be bound */
|
||||
public abstract void bindBufferToBindingPoint(int buffer, int bindingPoint);
|
||||
/** Requires both AbstractVertexAttribute to be bound */
|
||||
public abstract void unbindBuffersFromAllBindingPoint();
|
||||
/** Requires both AbstractVertexAttribute to be bound */
|
||||
public abstract void unbindBuffersFromBindingPoint(int bindingPoint);
|
||||
/** Requires both AbstractVertexAttribute to be bound */
|
||||
public abstract void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute);
|
||||
/** Requires both AbstractVertexAttribute to be bound */
|
||||
public abstract void completeAndCheck(int expectedStrideSize);
|
||||
|
||||
}
|
||||
-156
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.vertexAttribute;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import org.lwjgl.opengl.GL43;
|
||||
|
||||
/**
|
||||
* In OpenGL 4.3 and later, Vertex Attribute got a make-over.
|
||||
* Now it provides support for buffer binding points natively.
|
||||
* This means that setting up the VAO is just use ONE native call when
|
||||
* binding to a buffer. <br><br>
|
||||
*
|
||||
* Since I no longer need to implement binding points, I also no
|
||||
* longer needs to keep track of Pointers.
|
||||
*/
|
||||
public final class VertexAttributePostGL43 extends AbstractVertexAttribute
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||
.build();
|
||||
|
||||
|
||||
int numberOfBindingPoints = 0;
|
||||
int strideSize = 0;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
/** This will bind the {@link AbstractVertexAttribute} */
|
||||
public VertexAttributePostGL43()
|
||||
{
|
||||
super(); // also bind AbstractVertexAttribute
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// binding //
|
||||
//=========//
|
||||
|
||||
/** Requires both AbstractVertexAttribute and VertexBuffer to be bound */
|
||||
@Override
|
||||
public void bindBufferToAllBindingPoints(int buffer)
|
||||
{
|
||||
for (int i = 0; i < this.numberOfBindingPoints; i++)
|
||||
{
|
||||
GL43.glBindVertexBuffer(i, buffer, 0, this.strideSize);
|
||||
}
|
||||
}
|
||||
|
||||
/** Requires both AbstractVertexAttribute and VertexBuffer to be bound */
|
||||
@Override
|
||||
public void bindBufferToBindingPoint(int buffer, int bindingPoint)
|
||||
{
|
||||
GL43.glBindVertexBuffer(bindingPoint, buffer, 0, this.strideSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// unbinding //
|
||||
//===========//
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void unbindBuffersFromAllBindingPoint()
|
||||
{
|
||||
for (int i = 0; i < this.numberOfBindingPoints; i++)
|
||||
{
|
||||
GL43.glBindVertexBuffer(i, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void unbindBuffersFromBindingPoint(int bindingPoint)
|
||||
{
|
||||
GL43.glBindVertexBuffer(bindingPoint, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// manual attribute setting //
|
||||
//==========================//
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute)
|
||||
{
|
||||
if (attribute.useInteger)
|
||||
{
|
||||
GL43.glVertexAttribIFormat(attributeIndex, attribute.elementCount, attribute.glType, this.strideSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL43.glVertexAttribFormat(attributeIndex, attribute.elementCount, attribute.glType,
|
||||
attribute.normalized, this.strideSize); // Here strideSize is new attrib offset
|
||||
}
|
||||
|
||||
this.strideSize += attribute.byteSize;
|
||||
if (this.numberOfBindingPoints <= bindingPoint)
|
||||
{
|
||||
this.numberOfBindingPoints = bindingPoint + 1;
|
||||
}
|
||||
GL43.glVertexAttribBinding(attributeIndex, bindingPoint);
|
||||
GL43.glEnableVertexAttribArray(attributeIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============//
|
||||
// validation //
|
||||
//============//
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void completeAndCheck(int expectedStrideSize)
|
||||
{
|
||||
if (this.strideSize != expectedStrideSize)
|
||||
{
|
||||
LOGGER.error("Vertex Attribute calculated stride size " + this.strideSize +
|
||||
" does not match the provided expected stride size " + expectedStrideSize + "!");
|
||||
throw new IllegalArgumentException("Vertex Attribute Incorrect Format");
|
||||
}
|
||||
|
||||
LOGGER.info("Vertex Attribute (GL43+) completed. It contains " + this.numberOfBindingPoints
|
||||
+ " binding points and a stride size of " + this.strideSize);
|
||||
}
|
||||
|
||||
}
|
||||
-254
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.vertexAttribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
|
||||
public final class VertexAttributePreGL43 extends AbstractVertexAttribute
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||
.build();
|
||||
|
||||
|
||||
// I tried to use raw arrays as much as possible since those lookups
|
||||
// happen every frame, and the speed directly affects fps
|
||||
int strideSize = 0;
|
||||
int[][] bindingPointsToIndex;
|
||||
VertexPointer[] pointers;
|
||||
int[] pointersOffset;
|
||||
|
||||
TreeMap<Integer, TreeSet<Integer>> bindingPointsToIndexBuilder;
|
||||
ArrayList<VertexPointer> pointersBuilder;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
/** This will bind the {@link AbstractVertexAttribute} */
|
||||
public VertexAttributePreGL43()
|
||||
{
|
||||
super(); // also bind AbstractVertexAttribute
|
||||
this.bindingPointsToIndexBuilder = new TreeMap<>();
|
||||
this.pointersBuilder = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// binding //
|
||||
//=========//
|
||||
|
||||
/** Requires both AbstractVertexAttribute and VertexBuffer to be bound */
|
||||
@Override
|
||||
public void bindBufferToAllBindingPoints(int buffer)
|
||||
{
|
||||
for (int i = 0; i < this.pointers.length; i++)
|
||||
{
|
||||
GL32.glEnableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.pointers.length; i++)
|
||||
{
|
||||
VertexPointer pointer = this.pointers[i];
|
||||
if (pointer == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pointer.useInteger)
|
||||
{
|
||||
GL32.glVertexAttribIPointer(i, pointer.elementCount, pointer.glType,
|
||||
this.strideSize, this.pointersOffset[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glVertexAttribPointer(i, pointer.elementCount, pointer.glType,
|
||||
pointer.normalized, this.strideSize, this.pointersOffset[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Requires both AbstractVertexAttribute and VertexBuffer to be bound */
|
||||
@Override
|
||||
public void bindBufferToBindingPoint(int buffer, int bindingPoint)
|
||||
{
|
||||
int[] bindingPointIndexes = this.bindingPointsToIndex[bindingPoint];
|
||||
|
||||
for (int bindingPointIndex : bindingPointIndexes)
|
||||
{
|
||||
GL32.glEnableVertexAttribArray(bindingPointIndex);
|
||||
}
|
||||
|
||||
for (int bindingPointIndex : bindingPointIndexes)
|
||||
{
|
||||
VertexPointer pointer = this.pointers[bindingPointIndex];
|
||||
if (pointer == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pointer.useInteger)
|
||||
{
|
||||
GL32.glVertexAttribIPointer(bindingPointIndex, pointer.elementCount, pointer.glType,
|
||||
this.strideSize, this.pointersOffset[bindingPointIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glVertexAttribPointer(bindingPointIndex, pointer.elementCount, pointer.glType,
|
||||
pointer.normalized, this.strideSize, this.pointersOffset[bindingPointIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// unbinding //
|
||||
//===========//
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void unbindBuffersFromAllBindingPoint()
|
||||
{
|
||||
for (int i = 0; i < this.pointers.length; i++)
|
||||
{
|
||||
GL32.glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void unbindBuffersFromBindingPoint(int bindingPoint)
|
||||
{
|
||||
int[] bindingPointIndexes = this.bindingPointsToIndex[bindingPoint];
|
||||
for (int bindingPointIndex : bindingPointIndexes)
|
||||
{
|
||||
GL32.glDisableVertexAttribArray(bindingPointIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// manual attribute setting //
|
||||
//==========================//
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute)
|
||||
{
|
||||
TreeSet<Integer> intArray = this.bindingPointsToIndexBuilder.computeIfAbsent(bindingPoint, k -> new TreeSet<>());
|
||||
intArray.add(attributeIndex);
|
||||
|
||||
while (this.pointersBuilder.size() <= attributeIndex)
|
||||
{
|
||||
// This is dumb, but ArrayList doesn't have a resize, And this code
|
||||
// should only be run when it's building the Vertex Attribute anyway.
|
||||
this.pointersBuilder.add(null);
|
||||
}
|
||||
this.pointersBuilder.set(attributeIndex, attribute);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============//
|
||||
// validation //
|
||||
//============//
|
||||
|
||||
/** Requires AbstractVertexAttribute to be bound */
|
||||
@Override
|
||||
public void completeAndCheck(int expectedStrideSize)
|
||||
{
|
||||
int maxBindPointNumber = this.bindingPointsToIndexBuilder.lastKey();
|
||||
this.bindingPointsToIndex = new int[maxBindPointNumber + 1][];
|
||||
|
||||
this.bindingPointsToIndexBuilder.forEach((Integer i, TreeSet<Integer> set) ->
|
||||
{
|
||||
this.bindingPointsToIndex[i] = new int[set.size()];
|
||||
Iterator<Integer> iter = set.iterator();
|
||||
for (int j = 0; j < set.size(); j++)
|
||||
{
|
||||
this.bindingPointsToIndex[i][j] = iter.next();
|
||||
}
|
||||
});
|
||||
|
||||
this.pointers = this.pointersBuilder.toArray(new VertexPointer[this.pointersBuilder.size()]);
|
||||
this.pointersOffset = new int[this.pointers.length];
|
||||
this.pointersBuilder = null; // Release the builder
|
||||
this.bindingPointsToIndexBuilder = null; // Release the builder
|
||||
|
||||
// Check if all pointers are valid
|
||||
int currentOffset = 0;
|
||||
for (int i = 0; i < this.pointers.length; i++)
|
||||
{
|
||||
VertexPointer pointer = this.pointers[i];
|
||||
if (pointer == null)
|
||||
{
|
||||
LOGGER.warn("Vertex Attribute index " + i + " is not set! No index should be skipped normally!");
|
||||
continue;
|
||||
}
|
||||
this.pointersOffset[i] = currentOffset;
|
||||
currentOffset += pointer.byteSize;
|
||||
}
|
||||
|
||||
if (currentOffset != expectedStrideSize)
|
||||
{
|
||||
LOGGER.error("Vertex Attribute calculated stride size " + currentOffset +
|
||||
" does not match the provided expected stride size " + expectedStrideSize + "!");
|
||||
throw new IllegalArgumentException("Vertex Attribute Incorrect Format");
|
||||
}
|
||||
this.strideSize = currentOffset;
|
||||
LOGGER.info("Vertex Attribute (pre GL43) completed.");
|
||||
|
||||
// Debug logging
|
||||
LOGGER.debug("AttributeIndex: ElementCount, glType, normalized, strideSize, offset");
|
||||
|
||||
for (int i = 0; i < this.pointers.length; i++)
|
||||
{
|
||||
VertexPointer pointer = this.pointers[i];
|
||||
if (pointer == null)
|
||||
{
|
||||
LOGGER.debug(i + ": Null!!!!");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.debug(i + ": " + pointer.elementCount + ", " +
|
||||
pointer.glType + ", " + pointer.normalized + ", " + this.strideSize + ", " + this.pointersOffset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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.glObject.vertexAttribute;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public final class VertexPointer
|
||||
{
|
||||
public final int elementCount;
|
||||
public final int glType;
|
||||
public final boolean normalized;
|
||||
public final int byteSize;
|
||||
public final boolean useInteger;
|
||||
|
||||
|
||||
|
||||
// basic constructors //
|
||||
|
||||
public VertexPointer(int elementCount, int glType, boolean normalized, int byteSize, boolean useInteger)
|
||||
{
|
||||
this.elementCount = elementCount;
|
||||
this.glType = glType;
|
||||
this.normalized = normalized;
|
||||
this.byteSize = byteSize;
|
||||
this.useInteger = useInteger;
|
||||
}
|
||||
public VertexPointer(int elementCount, int glType, boolean normalized, int byteSize)
|
||||
{
|
||||
this(elementCount, glType, normalized, byteSize, false);
|
||||
}
|
||||
private static int _align(int bytes) { return MathUtil.ceilDiv(bytes, 4) * 4; }
|
||||
|
||||
|
||||
|
||||
// named constructors //
|
||||
|
||||
public static VertexPointer addFloatPointer(boolean normalized) { return new VertexPointer(1, GL32.GL_FLOAT, normalized, Float.BYTES); }
|
||||
public static VertexPointer addVec2Pointer(boolean normalized) { return new VertexPointer(2, GL32.GL_FLOAT, normalized, Float.BYTES * 2); }
|
||||
public static VertexPointer addVec3Pointer(boolean normalized) { return new VertexPointer(3, GL32.GL_FLOAT, normalized, Float.BYTES * 3); }
|
||||
public static VertexPointer addVec4Pointer(boolean normalized) { return new VertexPointer(4, GL32.GL_FLOAT, normalized, Float.BYTES * 4); }
|
||||
/** Always aligned to 4 bytes */
|
||||
public static VertexPointer addUnsignedBytePointer(boolean normalized, boolean useInteger) { return new VertexPointer(1, GL32.GL_UNSIGNED_BYTE, normalized, 4, useInteger); }
|
||||
/** aligned to 4 bytes */
|
||||
public static VertexPointer addUnsignedBytesPointer(int elementCount, boolean normalized, boolean useInteger)
|
||||
{ return new VertexPointer(elementCount, GL32.GL_UNSIGNED_BYTE, normalized, _align(elementCount), useInteger); }
|
||||
public static VertexPointer addUnsignedShortsPointer(int elementCount, boolean normalized, boolean useInteger)
|
||||
{ return new VertexPointer(elementCount, GL32.GL_UNSIGNED_SHORT, normalized, _align(elementCount * 2), useInteger); }
|
||||
public static VertexPointer addShortsPointer(int elementCount, boolean normalized, boolean useInteger) { return new VertexPointer(elementCount, GL32.GL_SHORT, normalized, _align(elementCount * 2), useInteger); }
|
||||
public static VertexPointer addIntPointer(boolean normalized, boolean useInteger) { return new VertexPointer(1, GL32.GL_INT, normalized, 4, useInteger); }
|
||||
public static VertexPointer addIVec2Pointer(boolean normalized, boolean useInteger) { return new VertexPointer(2, GL32.GL_INT, normalized, 8, useInteger); }
|
||||
public static VertexPointer addIVec3Pointer(boolean normalized, boolean useInteger) { return new VertexPointer(3, GL32.GL_INT, normalized, 12, useInteger); }
|
||||
public static VertexPointer addIVec4Pointer(boolean normalized, boolean useInteger) { return new VertexPointer(4, GL32.GL_INT, normalized, 16, useInteger); }
|
||||
|
||||
}
|
||||
+51
-203
@@ -1,199 +1,42 @@
|
||||
/*
|
||||
* 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.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||
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.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
/**
|
||||
* Handles rendering the wireframe particles
|
||||
* that are used for seeing what the system's doing.
|
||||
*/
|
||||
public class DebugRenderer
|
||||
public abstract class AbstractDebugWireframeRenderer implements IBindable
|
||||
{
|
||||
public static DebugRenderer INSTANCE = new DebugRenderer();
|
||||
protected static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
|
||||
.maxCountPerSecond(1)
|
||||
.build();
|
||||
|
||||
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
public static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
|
||||
.maxCountPerSecond(1)
|
||||
.build();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
|
||||
// rendering setup
|
||||
private ShaderProgram basicShader;
|
||||
private GLVertexBuffer vertexBuffer;
|
||||
private GLElementBuffer outlineIndexBuffer;
|
||||
private AbstractVertexAttribute va;
|
||||
private boolean init = false;
|
||||
protected final RendererLists rendererLists = new RendererLists();
|
||||
protected final PriorityBlockingQueue<BoxParticle> particles = new PriorityBlockingQueue<>();
|
||||
|
||||
// used when rendering
|
||||
private Mat4f transformationMatrixThisFrame;
|
||||
private Vec3f camPosFloatThisFrame;
|
||||
|
||||
|
||||
private final RendererLists rendererLists = new RendererLists();
|
||||
private final PriorityBlockingQueue<BoxParticle> particles = new PriorityBlockingQueue<>();
|
||||
|
||||
|
||||
|
||||
/** A box from 0,0,0 to 1,1,1 */
|
||||
private static final float[] BOX_VERTICES = {
|
||||
//region
|
||||
// Pos x y z
|
||||
0, 0, 0,
|
||||
1, 0, 0,
|
||||
1, 1, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
1, 0, 1,
|
||||
1, 1, 1,
|
||||
0, 1, 1,
|
||||
//endregion
|
||||
};
|
||||
|
||||
private static final int[] BOX_OUTLINE_INDICES = {
|
||||
//region
|
||||
0, 1,
|
||||
1, 2,
|
||||
2, 3,
|
||||
3, 0,
|
||||
|
||||
4, 5,
|
||||
5, 6,
|
||||
6, 7,
|
||||
7, 4,
|
||||
|
||||
0, 4,
|
||||
1, 5,
|
||||
2, 6,
|
||||
3, 7,
|
||||
//endregion
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
private DebugRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.init = true;
|
||||
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 3);
|
||||
this.basicShader = new ShaderProgram(
|
||||
"shaders/debug/vert.vert",
|
||||
"shaders/debug/frag.frag",
|
||||
"vPosition"
|
||||
);
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
// box vertices
|
||||
ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES);
|
||||
boxVerticesBuffer.order(ByteOrder.nativeOrder());
|
||||
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||
boxVerticesBuffer.rewind();
|
||||
this.vertexBuffer = new GLVertexBuffer(false);
|
||||
this.vertexBuffer.bind();
|
||||
this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES);
|
||||
|
||||
|
||||
// outline vertex indexes
|
||||
ByteBuffer boxOutlineBuffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES);
|
||||
boxOutlineBuffer.order(ByteOrder.nativeOrder());
|
||||
boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES);
|
||||
boxOutlineBuffer.rewind();
|
||||
this.outlineIndexBuffer = new GLElementBuffer(false);
|
||||
this.outlineIndexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// registration //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
public static void makeParticle(BoxParticle particle)
|
||||
{
|
||||
if (INSTANCE != null && Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get())
|
||||
{
|
||||
INSTANCE.particles.add(particle);
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(IDebugRenderable renderable, ConfigEntry<Boolean> config) { if (INSTANCE != null) { INSTANCE.addRenderer(renderable, config); } }
|
||||
public void addRenderer(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.rendererLists.addRenderable(renderable, config); }
|
||||
|
||||
public static void unregister(IDebugRenderable renderable, ConfigEntry<Boolean> config) { if (INSTANCE != null) { INSTANCE.removeRenderer(renderable, config); } }
|
||||
private void removeRenderer(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.rendererLists.removeRenderable(renderable, config); }
|
||||
|
||||
public static void clearRenderables() { INSTANCE.rendererLists.clearRenderables(); }
|
||||
|
||||
//endregion
|
||||
protected Mat4f dhMvmProjMatrixThisFrame;
|
||||
protected Vec3f camPosFloatThisFrame;
|
||||
|
||||
|
||||
|
||||
@@ -202,27 +45,17 @@ public class DebugRenderer
|
||||
//===========//
|
||||
//region
|
||||
|
||||
public void render(Mat4f transform)
|
||||
public void render(RenderParams renderParams)
|
||||
{
|
||||
this.transformationMatrixThisFrame = transform;
|
||||
this.dhMvmProjMatrixThisFrame = new Mat4f(renderParams.dhMvmProjMatrix);
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z);
|
||||
|
||||
this.init();
|
||||
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||
GLMC.enableDepthTest();
|
||||
|
||||
this.basicShader.bind();
|
||||
this.va.bind();
|
||||
this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId());
|
||||
|
||||
|
||||
this.outlineIndexBuffer.bind();
|
||||
this.rendererLists.render(this);
|
||||
|
||||
|
||||
// particle rendering
|
||||
// particle cleanup
|
||||
BoxParticle head = null;
|
||||
while ((head = this.particles.poll()) != null && head.isDead())
|
||||
{ /* remove dead particles */ }
|
||||
@@ -233,28 +66,41 @@ public class DebugRenderer
|
||||
}
|
||||
|
||||
|
||||
// box rendering
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
// particle rendering
|
||||
for (BoxParticle particle : this.particles)
|
||||
{
|
||||
// a new box is created each time since the height will be different based on the time it's lived
|
||||
this.renderBox(particle.createNewRenderBox());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void renderBox(Box box)
|
||||
public abstract void renderBox(Box box);
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// registration //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
public void makeParticle(BoxParticle particle)
|
||||
{
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(box.minPos.x - this.camPosFloatThisFrame.x, box.minPos.y - this.camPosFloatThisFrame.y, box.minPos.z - this.camPosFloatThisFrame.z);
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(box.maxPos.x - box.minPos.x, box.maxPos.y - box.minPos.y, box.maxPos.z - box.minPos.z));
|
||||
|
||||
Mat4f transformMatrix = this.transformationMatrixThisFrame.copy();
|
||||
transformMatrix.multiply(boxTransform);
|
||||
this.basicShader.setUniform(this.basicShader.getUniformLocation("uTransform"), transformMatrix);
|
||||
|
||||
this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color);
|
||||
|
||||
GL32.glDrawElements(GL32.GL_LINES, BOX_OUTLINE_INDICES.length, GL32.GL_UNSIGNED_INT, 0);
|
||||
if (Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get())
|
||||
{
|
||||
this.particles.add(particle);
|
||||
}
|
||||
}
|
||||
|
||||
public void register(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.addRenderer(renderable, config); }
|
||||
public void addRenderer(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.rendererLists.addRenderable(renderable, config); }
|
||||
|
||||
public void unregister(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.removeRenderer(renderable, config); }
|
||||
public void removeRenderer(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.rendererLists.removeRenderable(renderable, config); }
|
||||
|
||||
public void clearRenderables() { this.rendererLists.clearRenderables(); }
|
||||
|
||||
//endregion
|
||||
|
||||
@@ -318,7 +164,7 @@ public class DebugRenderer
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull DebugRenderer.BoxParticle particle)
|
||||
public int compareTo(@NotNull BoxParticle particle)
|
||||
{ return Long.compare(this.startMsTime + this.durationInMs, particle.startMsTime + particle.durationInMs); }
|
||||
|
||||
/** will change each time it's called based on the yChange value and time */
|
||||
@@ -340,7 +186,7 @@ public class DebugRenderer
|
||||
|
||||
}
|
||||
|
||||
private static class RendererLists
|
||||
protected static class RendererLists
|
||||
{
|
||||
public final LinkedList<WeakReference<IDebugRenderable>> generalRenderableList = new LinkedList<>();
|
||||
|
||||
@@ -383,7 +229,7 @@ public class DebugRenderer
|
||||
if (this.renderableListByConfig.containsKey(config))
|
||||
{
|
||||
LinkedList<WeakReference<IDebugRenderable>> renderableList = this.renderableListByConfig.get(config);
|
||||
this.removeRenderableFromInternalList(renderableList, renderable);
|
||||
this.removeRenderableFromInternalList(renderableList, renderable);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -433,7 +279,7 @@ public class DebugRenderer
|
||||
//===========//
|
||||
//region
|
||||
|
||||
public void render(DebugRenderer debugRenderer)
|
||||
public void render(AbstractDebugWireframeRenderer debugRenderer)
|
||||
{
|
||||
this.renderList(debugRenderer, this.generalRenderableList);
|
||||
|
||||
@@ -446,7 +292,7 @@ public class DebugRenderer
|
||||
}
|
||||
}
|
||||
}
|
||||
private void renderList(DebugRenderer debugRenderer, LinkedList<WeakReference<IDebugRenderable>> rendererList)
|
||||
private void renderList(AbstractDebugWireframeRenderer debugRenderer, LinkedList<WeakReference<IDebugRenderable>> rendererList)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
@@ -478,4 +324,6 @@ public class DebugRenderer
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
+6
-3
@@ -17,9 +17,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
|
||||
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;
|
||||
@@ -36,6 +37,7 @@ import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -50,6 +52,7 @@ public class BeaconRenderHandler
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IDhApiCustomRenderObjectFactory GENERIC_OBJECT_FACTORY = SingletonInjector.INSTANCE.get(IDhApiCustomRenderObjectFactory.class);
|
||||
|
||||
/** how often should we check if a beacon should be culled? */
|
||||
private static final int MAX_CULLING_FREQUENCY_IN_MS = 1_000;
|
||||
@@ -77,9 +80,9 @@ public class BeaconRenderHandler
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public BeaconRenderHandler(@NotNull GenericObjectRenderer renderer)
|
||||
public BeaconRenderHandler(@NotNull IDhGenericRenderer renderer)
|
||||
{
|
||||
this.activeBeaconBoxRenderGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(ModInfo.NAME+":Beacons", new ArrayList<>(0));
|
||||
this.activeBeaconBoxRenderGroup = GENERIC_OBJECT_FACTORY.createAbsolutePositionedGroup(ModInfo.NAME+":Beacons", new ArrayList<>(0));
|
||||
this.activeBeaconBoxRenderGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.activeBeaconBoxRenderGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.activeBeaconBoxRenderGroup.setSsaoEnabled(false);
|
||||
+17
-14
@@ -17,9 +17,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
|
||||
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;
|
||||
@@ -33,6 +34,7 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
@@ -49,6 +51,7 @@ public class CloudRenderHandler
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IDhApiCustomRenderObjectFactory GENERIC_OBJECT_FACTORY = SingletonInjector.INSTANCE.get(IDhApiCustomRenderObjectFactory.class);
|
||||
|
||||
private static final String CLOUD_RESOURCE_TEXTURE_PATH = "assets/distanthorizons/textures/clouds.png";
|
||||
|
||||
@@ -80,7 +83,7 @@ public class CloudRenderHandler
|
||||
= new IDhApiRenderableBoxGroup[(CLOUD_INSTANCE_RADIUS_COUNT * 2) + 1][(CLOUD_INSTANCE_RADIUS_COUNT * 2) + 1];
|
||||
|
||||
private final IDhClientLevel level;
|
||||
private final GenericObjectRenderer renderer;
|
||||
private final IDhGenericRenderer renderer;
|
||||
|
||||
/** cached array so we don't need to re-create it each frame for each cloud group */
|
||||
private final Vec3d[] cullingCorners = new Vec3d[]
|
||||
@@ -102,7 +105,7 @@ public class CloudRenderHandler
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public CloudRenderHandler(IDhClientLevel level, GenericObjectRenderer renderer)
|
||||
public CloudRenderHandler(IDhClientLevel level, IDhGenericRenderer renderer)
|
||||
{
|
||||
this.level = level;
|
||||
this.renderer = renderer;
|
||||
@@ -270,7 +273,7 @@ public class CloudRenderHandler
|
||||
{
|
||||
for (int z = -CLOUD_INSTANCE_RADIUS_COUNT; z <= CLOUD_INSTANCE_RADIUS_COUNT; z++)
|
||||
{
|
||||
IDhApiRenderableBoxGroup boxGroup = GenericRenderObjectFactory.INSTANCE.createRelativePositionedGroup(
|
||||
IDhApiRenderableBoxGroup boxGroup = GENERIC_OBJECT_FACTORY.createRelativePositionedGroup(
|
||||
ModInfo.NAME + ":Clouds",
|
||||
new DhApiVec3d(0, 0, 0), // the offset will be set during rendering
|
||||
boxList);
|
||||
@@ -316,16 +319,16 @@ public class CloudRenderHandler
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.renderer.getInstancedRenderingAvailable())
|
||||
{
|
||||
if (!this.disabledWarningLogged)
|
||||
{
|
||||
this.disabledWarningLogged = true;
|
||||
LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled.");
|
||||
}
|
||||
boxGroup.setActive(false);
|
||||
return;
|
||||
}
|
||||
//if (!this.renderer.getInstancedRenderingAvailable())
|
||||
//{
|
||||
// if (!this.disabledWarningLogged)
|
||||
// {
|
||||
// this.disabledWarningLogged = true;
|
||||
// LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled.");
|
||||
// }
|
||||
// boxGroup.setActive(false);
|
||||
// return;
|
||||
//}
|
||||
|
||||
IClientLevelWrapper clientLevelWrapper = this.level.getClientLevelWrapper();
|
||||
if (clientLevelWrapper == null)
|
||||
-164
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* 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.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.DhFadeShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.FadeApplyShader;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL43C;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles fading MC and DH together via {@link DhFadeShader} and {@link FadeApplyShader}. <br><br>
|
||||
*
|
||||
* {@link DhFadeShader} - draws the Fade to a texture. <br>
|
||||
* {@link FadeApplyShader} - draws the Fade texture to DH's framebuffer. <br>
|
||||
*/
|
||||
public class DhFadeRenderer
|
||||
{
|
||||
|
||||
public static DhFadeRenderer INSTANCE = new DhFadeRenderer();
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int fadeFramebuffer = -1;
|
||||
|
||||
private int fadeTexture = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private DhFadeRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
DhFadeShader.INSTANCE.init();
|
||||
FadeApplyShader.INSTANCE.init();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.fadeFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.fadeFramebuffer);
|
||||
this.fadeFramebuffer = -1;
|
||||
}
|
||||
|
||||
this.fadeFramebuffer = GL32.glGenFramebuffers();
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fadeFramebuffer);
|
||||
|
||||
|
||||
if (this.fadeTexture != -1)
|
||||
{
|
||||
GLMC.glDeleteTextures(this.fadeTexture);
|
||||
this.fadeTexture = -1;
|
||||
}
|
||||
|
||||
this.fadeTexture = GL32.glGenTextures();
|
||||
{
|
||||
GLMC.glBindTexture(this.fadeTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||
|
||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fadeTexture, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
|
||||
{
|
||||
try
|
||||
{
|
||||
profiler.push("Fade Generate");
|
||||
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
|
||||
DhFadeShader.INSTANCE.frameBuffer = this.fadeFramebuffer;
|
||||
DhFadeShader.INSTANCE.setProjectionMatrix(mcModelViewMatrix, mcProjectionMatrix);
|
||||
DhFadeShader.INSTANCE.render(partialTicks);
|
||||
|
||||
// restored so we can write the fade texture to the main frame buffer
|
||||
//mcState.restore();
|
||||
|
||||
profiler.popPush("Fade Apply");
|
||||
|
||||
FadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
|
||||
FadeApplyShader.INSTANCE.readFramebuffer = DhFadeShader.INSTANCE.frameBuffer;
|
||||
FadeApplyShader.INSTANCE.drawFramebuffer = LodRenderer.INSTANCE.getActiveFramebufferId();
|
||||
FadeApplyShader.INSTANCE.render(partialTicks);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unexpected error during fade render, error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
profiler.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-226
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* 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.override.rendering.IDhApiShaderProgram;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.Shader;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttributePostGL43;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttributePreGL43;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
/**
|
||||
* Handles rendering the normal LOD terrain.
|
||||
* @see LodQuadBuilder
|
||||
*/
|
||||
public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShaderProgram
|
||||
{
|
||||
public final AbstractVertexAttribute vao;
|
||||
|
||||
// Uniforms
|
||||
public int uCombinedMatrix = -1;
|
||||
public int uModelOffset = -1;
|
||||
public int uWorldYOffset = -1;
|
||||
|
||||
public int uMircoOffset = -1;
|
||||
public int uEarthRadius = -1;
|
||||
public int uLightMap = -1;
|
||||
|
||||
// fragment shader uniforms
|
||||
public int uClipDistance = -1;
|
||||
public int uDitherDhRendering = -1;
|
||||
|
||||
// Noise Uniforms
|
||||
public int uNoiseEnabled = -1;
|
||||
public int uNoiseSteps = -1;
|
||||
public int uNoiseIntensity = -1;
|
||||
public int uNoiseDropoff = -1;
|
||||
|
||||
// Debug Uniform
|
||||
public int uIsWhiteWorld = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
// This will bind AbstractVertexAttribute
|
||||
public DhTerrainShaderProgram()
|
||||
{
|
||||
super(
|
||||
"shaders/standard.vert",
|
||||
"shaders/flat_shaded.frag",
|
||||
new String[]{"vPosition", "color"}
|
||||
);
|
||||
|
||||
this.uCombinedMatrix = this.getUniformLocation("uCombinedMatrix");
|
||||
this.uModelOffset = this.getUniformLocation("uModelOffset");
|
||||
this.uWorldYOffset = this.getUniformLocation("uWorldYOffset");
|
||||
this.uDitherDhRendering = this.getUniformLocation("uDitherDhRendering");
|
||||
this.uMircoOffset = this.getUniformLocation("uMircoOffset");
|
||||
this.uEarthRadius = this.getUniformLocation("uEarthRadius");
|
||||
|
||||
this.uLightMap = this.getUniformLocation("uLightMap");
|
||||
|
||||
// Fog/Clip Uniforms
|
||||
this.uClipDistance = this.getUniformLocation("uClipDistance");
|
||||
|
||||
// Noise Uniforms
|
||||
this.uNoiseEnabled = this.getUniformLocation("uNoiseEnabled");
|
||||
this.uNoiseSteps = this.getUniformLocation("uNoiseSteps");
|
||||
this.uNoiseIntensity = this.getUniformLocation("uNoiseIntensity");
|
||||
this.uNoiseDropoff = this.getUniformLocation("uNoiseDropoff");
|
||||
|
||||
// Debug Uniform
|
||||
this.uIsWhiteWorld = this.getUniformLocation("uIsWhiteWorld");
|
||||
|
||||
|
||||
if (GLProxy.getInstance().vertexAttributeBufferBindingSupported)
|
||||
{
|
||||
this.vao = new VertexAttributePostGL43(); // also binds AbstractVertexAttribute
|
||||
}
|
||||
else
|
||||
{
|
||||
this.vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute
|
||||
}
|
||||
this.vao.bind();
|
||||
|
||||
// short: x, y, z, meta
|
||||
// meta: byte skylight, byte blocklight, byte microOffset
|
||||
this.vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true));
|
||||
// byte: r, g, b, a
|
||||
this.vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false));
|
||||
// byte: iris material ID, normal index, 2 spacers
|
||||
this.vao.setVertexAttribute(0, 2, VertexPointer.addUnsignedBytesPointer(4, true, true));
|
||||
|
||||
try
|
||||
{
|
||||
int vertexByteCount = LodUtil.DH_VERTEX_FORMAT.getByteSize();
|
||||
this.vao.completeAndCheck(vertexByteCount);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
System.out.println(LodUtil.DH_VERTEX_FORMAT);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public void bind()
|
||||
{
|
||||
super.bind();
|
||||
this.vao.bind();
|
||||
}
|
||||
@Override
|
||||
public void unbind()
|
||||
{
|
||||
super.unbind();
|
||||
this.vao.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free()
|
||||
{
|
||||
this.vao.free();
|
||||
super.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindVertexBuffer(int vbo) { this.vao.bindBufferToAllBindingPoints(vbo); }
|
||||
|
||||
@Override
|
||||
public void fillUniformData(DhApiRenderParam renderParameters)
|
||||
{
|
||||
Mat4f combinedMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||
|
||||
super.bind();
|
||||
|
||||
// uniforms
|
||||
this.setUniform(this.uCombinedMatrix, combinedMatrix);
|
||||
this.setUniform(this.uMircoOffset, 0.01f); // 0.01 block offset
|
||||
|
||||
this.setUniform(this.uLightMap, ILightMapWrapper.BOUND_INDEX);
|
||||
|
||||
this.setUniform(this.uWorldYOffset, (float) renderParameters.worldYOffset);
|
||||
|
||||
this.setUniform(this.uDitherDhRendering, Config.Client.Advanced.Graphics.Quality.ditherDhFade.get());
|
||||
|
||||
float curveRatio = Config.Client.Advanced.Graphics.Experimental.earthCurveRatio.get();
|
||||
if (curveRatio < -1.0f || curveRatio > 1.0f)
|
||||
{
|
||||
curveRatio = /*6371KM*/ 6371000.0f / curveRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// disable curvature if the config value is between -1 and 1
|
||||
curveRatio = 0.0f;
|
||||
}
|
||||
this.setUniform(this.uEarthRadius, curveRatio);
|
||||
|
||||
// Noise Uniforms
|
||||
this.setUniform(this.uNoiseEnabled, Config.Client.Advanced.Graphics.NoiseTexture.enableNoiseTexture.get());
|
||||
this.setUniform(this.uNoiseSteps, Config.Client.Advanced.Graphics.NoiseTexture.noiseSteps.get());
|
||||
this.setUniform(this.uNoiseIntensity, Config.Client.Advanced.Graphics.NoiseTexture.noiseIntensity.get());
|
||||
this.setUniform(this.uNoiseDropoff, Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get());
|
||||
|
||||
// Debug
|
||||
this.setUniform(this.uIsWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
|
||||
|
||||
// Clip Uniform
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocks();
|
||||
if (!Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
dhNearClipDistance += 16f;
|
||||
}
|
||||
this.setUniform(this.uClipDistance, dhNearClipDistance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModelOffsetPos(DhApiVec3f modelOffsetPos) { this.setUniform(this.uModelOffset, new Vec3f(modelOffsetPos)); }
|
||||
|
||||
@Override
|
||||
public int getId() { return this.id; }
|
||||
|
||||
/** The base DH render program should always render */
|
||||
@Override
|
||||
public boolean overrideThisFrame() { return true; }
|
||||
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* 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.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.FogApplyShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.FogShader;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL43C;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles adding SSAO via {@link FogShader} and {@link FogApplyShader}. <br><br>
|
||||
*
|
||||
* {@link FogShader} - draws the Fog to a texture. <br>
|
||||
* {@link FogApplyShader} - draws the Fog texture to DH's FrameBuffer. <br>
|
||||
*/
|
||||
public class FogRenderer
|
||||
{
|
||||
public static FogRenderer INSTANCE = new FogRenderer();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int fogFramebuffer = -1;
|
||||
|
||||
private int fogTexture = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private FogRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
FogShader.INSTANCE.init();
|
||||
FogApplyShader.INSTANCE.init();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.fogFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.fogFramebuffer);
|
||||
this.fogFramebuffer = -1;
|
||||
}
|
||||
|
||||
if (this.fogTexture != -1)
|
||||
{
|
||||
GLMC.glDeleteTextures(this.fogTexture);
|
||||
this.fogTexture = -1;
|
||||
}
|
||||
|
||||
this.fogFramebuffer = GL32.glGenFramebuffers();
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fogFramebuffer);
|
||||
|
||||
this.fogTexture = GLMC.glGenTextures();
|
||||
{
|
||||
GLMC.glBindTexture(this.fogTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fogTexture, 0);
|
||||
|
||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(Mat4f modelViewProjectionMatrix, float partialTicks)
|
||||
{
|
||||
// GLState needed in MC 1.16.5 probably due to MC not manually setting each GL state they need before the next rendering step
|
||||
try (GLState state = new GLState())
|
||||
{
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
FogShader.INSTANCE.frameBuffer = this.fogFramebuffer;
|
||||
FogShader.INSTANCE.setProjectionMatrix(modelViewProjectionMatrix);
|
||||
FogShader.INSTANCE.render(partialTicks);
|
||||
|
||||
FogApplyShader.INSTANCE.fogTexture = this.fogTexture;
|
||||
FogApplyShader.INSTANCE.render(partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
FogShader.INSTANCE.free();
|
||||
FogApplyShader.INSTANCE.free();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-4
@@ -17,17 +17,14 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
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.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
import java.util.List;
|
||||
+1
-1
@@ -21,6 +21,6 @@ package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
public interface IDebugRenderable
|
||||
{
|
||||
void debugRender(DebugRenderer r);
|
||||
void debugRender(AbstractDebugWireframeRenderer r);
|
||||
|
||||
}
|
||||
|
||||
+73
-485
@@ -19,43 +19,22 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiTextureCreatedParam;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
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.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.texture.*;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.*;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* This is where all the magic happens. <br>
|
||||
@@ -73,46 +52,42 @@ public class LodRenderer
|
||||
.build();
|
||||
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
|
||||
|
||||
public static final LodRenderer INSTANCE = new LodRenderer();
|
||||
|
||||
|
||||
private boolean vanillaSettingsOverridden = false;
|
||||
private boolean renderersBound = false;
|
||||
|
||||
// these ID's either what any render is currently using (since only one renderer can be active at a time), or just used previously
|
||||
private int activeFramebufferId = -1;
|
||||
private int activeColorTextureId = -1;
|
||||
private int activeDepthTextureId = -1;
|
||||
private int textureWidth;
|
||||
private int textureHeight;
|
||||
|
||||
|
||||
private IDhApiShaderProgram lodRenderProgram = null;
|
||||
public QuadElementBuffer quadIBO = null;
|
||||
private boolean renderObjectsCreated = false;
|
||||
|
||||
// framebuffer and texture ID's for this renderer
|
||||
private IDhApiFramebuffer framebuffer;
|
||||
/** will be null if MC's framebuffer is being used since MC already has a color texture */
|
||||
@Nullable
|
||||
private DhColorTexture nullableColorTexture;
|
||||
private DHDepthTexture depthTexture;
|
||||
/**
|
||||
* If true the {@link LodRenderer#framebuffer} is the same as MC's.
|
||||
* This should only be true in the case of Optifine so LODs won't be overwritten when shaders are enabled.
|
||||
*/
|
||||
private boolean usingMcFramebuffer = false;
|
||||
private IDhMetaRenderer metaRenderer;
|
||||
private IDhTerrainRenderer terrainRenderer;
|
||||
private IDhSsaoRenderer ssaoRenderer;
|
||||
private IDhFogRenderer fogRenderer;
|
||||
private IDhFarFadeRenderer farFadeRenderer;
|
||||
private AbstractDebugWireframeRenderer debugWireframeRenderer;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
private LodRenderer() { }
|
||||
|
||||
private void bindRenderers()
|
||||
{
|
||||
this.metaRenderer = SingletonInjector.INSTANCE.get(IDhMetaRenderer.class);
|
||||
this.terrainRenderer = SingletonInjector.INSTANCE.get(IDhTerrainRenderer.class);
|
||||
this.ssaoRenderer = SingletonInjector.INSTANCE.get(IDhSsaoRenderer.class);
|
||||
this.fogRenderer = SingletonInjector.INSTANCE.get(IDhFogRenderer.class);
|
||||
this.farFadeRenderer = SingletonInjector.INSTANCE.get(IDhFarFadeRenderer.class);
|
||||
this.debugWireframeRenderer = SingletonInjector.INSTANCE.get(AbstractDebugWireframeRenderer.class);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
@@ -142,6 +117,7 @@ public class LodRenderer
|
||||
//====================//
|
||||
// validate rendering //
|
||||
//====================//
|
||||
//region
|
||||
|
||||
boolean deferTransparentRendering = DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
|
||||
if (runningDeferredPass
|
||||
@@ -152,33 +128,37 @@ public class LodRenderer
|
||||
boolean firstPass = !runningDeferredPass;
|
||||
|
||||
// RenderParams parameter validation should be done before this
|
||||
if (!renderParams.validationRun)
|
||||
if (!renderParams.hasBeenValidated)
|
||||
{
|
||||
throw new IllegalArgumentException("Render parameters validation");
|
||||
}
|
||||
|
||||
RenderBufferHandler renderBufferHandler = renderParams.renderBufferHandler;
|
||||
GenericObjectRenderer genericRenderer = renderParams.genericRenderer;
|
||||
ILightMapWrapper lightmap = renderParams.lightmap;
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// rendering setup //
|
||||
//=================//
|
||||
//region
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderSetupEvent.class, renderParams);
|
||||
profiler.push("LOD GL setup");
|
||||
|
||||
if (!this.renderObjectsCreated)
|
||||
if (!this.renderersBound)
|
||||
{
|
||||
this.bindRenderers();
|
||||
this.renderersBound = true;
|
||||
}
|
||||
|
||||
RenderBufferHandler renderBufferHandler = renderParams.renderBufferHandler;
|
||||
IDhGenericRenderer genericRenderer = renderParams.genericRenderer;
|
||||
|
||||
|
||||
this.metaRenderer.runRenderPassSetup(renderParams);
|
||||
|
||||
if (!this.vanillaSettingsOverridden)
|
||||
{
|
||||
boolean setupSuccess = this.createRenderObjects();
|
||||
if (!setupSuccess)
|
||||
{
|
||||
// shouldn't normally happen, but just in case
|
||||
return;
|
||||
}
|
||||
|
||||
// only do this once, that way they can still be reverted if desired
|
||||
if (Config.Client.Advanced.Graphics.overrideVanillaGraphicsSettings.get())
|
||||
{
|
||||
@@ -189,27 +169,17 @@ public class LodRenderer
|
||||
MC.disableFabulousTransparency();
|
||||
}
|
||||
|
||||
this.renderObjectsCreated = true;
|
||||
this.vanillaSettingsOverridden = true;
|
||||
}
|
||||
|
||||
this.setGLState(renderParams, firstPass);
|
||||
|
||||
lightmap.bind();
|
||||
this.quadIBO.bind();
|
||||
|
||||
if (firstPass)
|
||||
{
|
||||
// we only need to sort/cull the LODs during the first frame
|
||||
// we only need to sort/cull the LODs at the start of the frame
|
||||
profiler.popPush("LOD build render list");
|
||||
renderBufferHandler.buildRenderList(renderParams);
|
||||
}
|
||||
|
||||
IDhApiShaderProgram lodShaderProgram = this.lodRenderProgram;
|
||||
IDhApiShaderProgram lodShaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||
if (lodShaderProgramOverride != null && lodShaderProgram.overrideThisFrame())
|
||||
{
|
||||
lodShaderProgram = lodShaderProgramOverride;
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
@@ -219,6 +189,10 @@ public class LodRenderer
|
||||
|
||||
if (!runningDeferredPass)
|
||||
{
|
||||
this.metaRenderer.clearDhDepthAndColorTextures(renderParams);
|
||||
|
||||
|
||||
|
||||
//=========================//
|
||||
// opaque and non-deferred //
|
||||
// transparent rendering //
|
||||
@@ -226,7 +200,8 @@ public class LodRenderer
|
||||
|
||||
// opaque LODs
|
||||
profiler.popPush("LOD Opaque");
|
||||
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ true);
|
||||
|
||||
this.renderLodPass(this.terrainRenderer, renderBufferHandler, renderParams, /*opaquePass*/ true, profiler);
|
||||
|
||||
// custom objects with SSAO
|
||||
if (Config.Client.Advanced.Graphics.GenericRendering.enableGenericRendering.get())
|
||||
@@ -239,7 +214,7 @@ public class LodRenderer
|
||||
if (Config.Client.Advanced.Graphics.Ssao.enableSsao.get())
|
||||
{
|
||||
profiler.popPush("LOD SSAO");
|
||||
SSAORenderer.INSTANCE.render(new Mat4f(renderParams.dhProjectionMatrix), renderParams.partialTicks);
|
||||
this.ssaoRenderer.render(renderParams);
|
||||
}
|
||||
|
||||
// custom objects without SSAO
|
||||
@@ -254,19 +229,15 @@ public class LodRenderer
|
||||
&& Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
|
||||
{
|
||||
profiler.popPush("LOD Transparent");
|
||||
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ false);
|
||||
this.renderLodPass(this.terrainRenderer, renderBufferHandler, renderParams, /*opaquePass*/ false, profiler);
|
||||
}
|
||||
|
||||
// far plane clip fading
|
||||
if (Config.Client.Advanced.Graphics.Quality.dhFadeFarClipPlane.get()
|
||||
// the fade shader messes with the GL state in a way Iris doesn't like,
|
||||
// so skip it if a shader is active
|
||||
&& (IRIS_ACCESSOR == null || !IRIS_ACCESSOR.isShaderPackInUse()))
|
||||
&& IRIS_ACCESSOR == null)
|
||||
{
|
||||
profiler.popPush("Fade Far Clip Fade");
|
||||
DhFadeRenderer.INSTANCE.render(
|
||||
new Mat4f(renderParams.mcModelViewMatrix), new Mat4f(renderParams.mcProjectionMatrix),
|
||||
renderParams.partialTicks, profiler);
|
||||
this.farFadeRenderer.render(renderParams);
|
||||
}
|
||||
|
||||
// fog
|
||||
@@ -275,11 +246,8 @@ public class LodRenderer
|
||||
|| renderParams.vanillaFogEnabled)
|
||||
{
|
||||
profiler.popPush("LOD Fog");
|
||||
|
||||
Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
||||
|
||||
FogRenderer.INSTANCE.render(combinedMatrix, renderParams.partialTicks);
|
||||
|
||||
this.fogRenderer.render(renderParams);
|
||||
}
|
||||
|
||||
|
||||
@@ -291,25 +259,9 @@ public class LodRenderer
|
||||
if (Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get())
|
||||
{
|
||||
profiler.popPush("Debug wireframes");
|
||||
|
||||
Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
||||
|
||||
// Note: this can be very slow if a lot of boxes are being rendered
|
||||
DebugRenderer.INSTANCE.render(combinedMatrix);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===================//
|
||||
// optifine clean up //
|
||||
//===================//
|
||||
|
||||
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);
|
||||
|
||||
// Note: this can be very slow if a lot of boxes are being rendered
|
||||
this.debugWireframeRenderer.render(renderParams);
|
||||
}
|
||||
|
||||
|
||||
@@ -321,34 +273,30 @@ public class LodRenderer
|
||||
boolean cancelApplyShader = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeApplyShaderRenderEvent.class, renderParams);
|
||||
if (!cancelApplyShader)
|
||||
{
|
||||
profiler.popPush("LOD Apply");
|
||||
|
||||
// Copy the LOD framebuffer to Minecraft's framebuffer
|
||||
DhApplyShader.INSTANCE.render(renderParams.partialTicks);
|
||||
profiler.popPush("Apply to MC");
|
||||
this.metaRenderer.applyToMcTexture(renderParams);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//====================//
|
||||
// deferred rendering //
|
||||
//====================//
|
||||
|
||||
|
||||
if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
|
||||
{
|
||||
profiler.popPush("LOD Transparent");
|
||||
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ false);
|
||||
|
||||
|
||||
this.renderLodPass(this.terrainRenderer, renderBufferHandler, renderParams, /*opaquePass*/ false, profiler);
|
||||
|
||||
|
||||
if (Config.Client.Advanced.Graphics.Fog.enableDhFog.get()
|
||||
// this is done to fix issues with: underwater fog, blindness effect, etc.
|
||||
|| renderParams.vanillaFogEnabled)
|
||||
{
|
||||
profiler.popPush("LOD Fog");
|
||||
|
||||
Mat4f combinedMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderParams.dhModelViewMatrix);
|
||||
|
||||
FogRenderer.INSTANCE.render(combinedMatrix, renderParams.partialTicks);
|
||||
|
||||
this.fogRenderer.render(renderParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,9 +310,8 @@ public class LodRenderer
|
||||
profiler.popPush("LOD cleanup");
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams);
|
||||
|
||||
lightmap.unbind();
|
||||
this.quadIBO.unbind();
|
||||
lodShaderProgram.unbind();
|
||||
this.metaRenderer.runRenderPassCleanup(renderParams);
|
||||
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
@@ -375,385 +322,26 @@ public class LodRenderer
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// Setup Functions //
|
||||
//=================//
|
||||
//region
|
||||
|
||||
private void setGLState(
|
||||
DhApiRenderParam renderEventParam,
|
||||
boolean firstPass)
|
||||
{
|
||||
//===================//
|
||||
// framebuffer setup //
|
||||
//===================//
|
||||
|
||||
// get the active framebuffer
|
||||
IDhApiFramebuffer framebuffer = this.framebuffer;
|
||||
IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class);
|
||||
if (framebufferOverride != null && framebufferOverride.overrideThisFrame())
|
||||
{
|
||||
framebuffer = framebufferOverride;
|
||||
}
|
||||
this.activeFramebufferId = framebuffer.getId();
|
||||
framebuffer.bind();
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// bindings //
|
||||
//==========//
|
||||
|
||||
// by default draw everything as triangles
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
|
||||
GLMC.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ZERO);
|
||||
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
|
||||
// Enable depth test and depth mask
|
||||
GLMC.enableDepthTest();
|
||||
GLMC.glDepthFunc(GL32.GL_LESS);
|
||||
GLMC.enableDepthMask();
|
||||
|
||||
// This is required for MC versions 1.21.5+
|
||||
// due to MC updating the lightmap by changing the viewport size
|
||||
GL32.glViewport(0, 0, this.textureWidth, this.textureHeight);
|
||||
|
||||
this.lodRenderProgram.bind();
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// uniforms //
|
||||
//==========//
|
||||
|
||||
IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||
if (shaderProgramOverride != null)
|
||||
{
|
||||
shaderProgramOverride.fillUniformData(renderEventParam);
|
||||
}
|
||||
|
||||
this.lodRenderProgram.fillUniformData(renderEventParam);
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// texture setup //
|
||||
//===============//
|
||||
|
||||
// resize the textures if needed
|
||||
if (MC_RENDER.getTargetFramebufferViewportWidth() != this.textureWidth
|
||||
|| MC_RENDER.getTargetFramebufferViewportHeight() != this.textureHeight)
|
||||
{
|
||||
// just resizing the textures doesn't work when Optifine is present,
|
||||
// so recreate the textures with the new size instead
|
||||
this.createAndBindTextures();
|
||||
}
|
||||
|
||||
|
||||
// set the active textures
|
||||
this.activeDepthTextureId = this.depthTexture.getTextureId();
|
||||
|
||||
if (this.nullableColorTexture != null)
|
||||
{
|
||||
this.activeColorTextureId = this.nullableColorTexture.getTextureId();
|
||||
}
|
||||
else
|
||||
{
|
||||
// get MC's color texture
|
||||
this.activeColorTextureId = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
}
|
||||
|
||||
|
||||
// needs to be fired after all the textures have been created/bound
|
||||
boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderEventParam);
|
||||
if (clearTextures)
|
||||
{
|
||||
GL32.glClearDepth(1.0);
|
||||
|
||||
float[] clearColorValues = new float[4];
|
||||
GL32.glGetFloatv(GL32.GL_COLOR_CLEAR_VALUE, clearColorValues);
|
||||
GL32.glClearColor(clearColorValues[0], clearColorValues[1], clearColorValues[2], 1.0f);
|
||||
|
||||
if (this.usingMcFramebuffer && framebufferOverride == null)
|
||||
{
|
||||
// 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
|
||||
framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||
|
||||
|
||||
// don't clear the color texture, that removes the sky
|
||||
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
else if (firstPass)
|
||||
{
|
||||
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private boolean createRenderObjects()
|
||||
{
|
||||
if (this.renderObjectsCreated)
|
||||
{
|
||||
LOGGER.warn("Renderer setup called but it has already completed setup!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// GLProxy should have already been created by this point, but just in case create it now
|
||||
GLProxy.getInstance();
|
||||
|
||||
|
||||
|
||||
LOGGER.info("Setting up renderer");
|
||||
this.lodRenderProgram = new DhTerrainShaderProgram();
|
||||
|
||||
this.quadIBO = new QuadElementBuffer();
|
||||
this.quadIBO.reserve(LodBufferContainer.MAX_QUADS_PER_BUFFER);
|
||||
|
||||
|
||||
// create or get the frame buffer
|
||||
if (AbstractOptifineAccessor.optifinePresent())
|
||||
{
|
||||
// use MC/Optifine's default Framebuffer so shaders won't remove the LODs
|
||||
int currentFramebufferId = MC_RENDER.getTargetFramebuffer();
|
||||
this.framebuffer = new DhFramebuffer(currentFramebufferId);
|
||||
this.usingMcFramebuffer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal use case
|
||||
this.framebuffer = new DhFramebuffer();
|
||||
this.usingMcFramebuffer = false;
|
||||
}
|
||||
|
||||
// create and bind the necessary textures
|
||||
this.createAndBindTextures();
|
||||
|
||||
if(this.framebuffer.getStatus() != GL32.GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
// This generally means something wasn't bound, IE missing either the color or depth texture
|
||||
LOGGER.warn("Framebuffer ["+this.framebuffer.getId()+"] isn't complete.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOGGER.info("Renderer setup complete");
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "deprecation" ) // done to ignore DhApiColorDepthTextureCreatedEvent
|
||||
private void createAndBindTextures()
|
||||
{
|
||||
int oldWidth = this.textureWidth;
|
||||
int oldHeight = this.textureHeight;
|
||||
this.textureWidth = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
this.textureHeight = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
|
||||
DhApiTextureCreatedParam textureCreatedParam = new DhApiTextureCreatedParam(
|
||||
oldWidth, oldHeight,
|
||||
this.textureWidth, this.textureHeight
|
||||
);
|
||||
|
||||
|
||||
// DhApiColorDepthTextureCreatedEvent needs to be kept around since old versions of Iris need it
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiColorDepthTextureCreatedEvent.class, new DhApiColorDepthTextureCreatedEvent.EventParam(textureCreatedParam));
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeColorDepthTextureCreatedEvent.class, textureCreatedParam);
|
||||
|
||||
|
||||
// also update the framebuffer override if present
|
||||
IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class);
|
||||
|
||||
|
||||
this.depthTexture = new DHDepthTexture(this.textureWidth, this.textureHeight, EDhDepthBufferFormat.DEPTH32F);
|
||||
this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||
if (framebufferOverride != null)
|
||||
{
|
||||
framebufferOverride.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||
}
|
||||
|
||||
// if we are using MC's frame buffer, a color texture is already present and shouldn't need to be bound
|
||||
if (!this.usingMcFramebuffer)
|
||||
{
|
||||
this.nullableColorTexture = DhColorTexture.builder().setDimensions(this.textureWidth, this.textureHeight)
|
||||
.setInternalFormat(EDhInternalTextureFormat.RGBA8)
|
||||
.setPixelType(EDhPixelType.UNSIGNED_BYTE)
|
||||
.setPixelFormat(EDhPixelFormat.RGBA)
|
||||
.build();
|
||||
|
||||
this.framebuffer.addColorAttachment(0, this.nullableColorTexture.getTextureId());
|
||||
if (framebufferOverride != null)
|
||||
{
|
||||
framebufferOverride.addColorAttachment(0, this.nullableColorTexture.getTextureId());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.nullableColorTexture = null;
|
||||
}
|
||||
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterColorDepthTextureCreatedEvent.class, textureCreatedParam);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// LOD rendering //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
private void renderLodPass(IDhApiShaderProgram shaderProgram, RenderBufferHandler lodBufferHandler, RenderParams renderEventParam, boolean opaquePass)
|
||||
private void renderLodPass(IDhTerrainRenderer lodRenderer, RenderBufferHandler lodBufferHandler, RenderParams renderEventParam, boolean opaquePass, IProfilerWrapper profilerWrapper)
|
||||
{
|
||||
//=======================//
|
||||
// debug wireframe setup //
|
||||
//=======================//
|
||||
|
||||
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
|
||||
if (renderWireframe)
|
||||
{
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||
GLMC.disableFaceCulling();
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
if (!opaquePass)
|
||||
{
|
||||
GLMC.enableBlend();
|
||||
GLMC.enableDepthTest();
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMC.disableBlend();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||
|
||||
if (IRIS_ACCESSOR != null)
|
||||
SortedArraySet<LodBufferContainer> lodBufferContainer = lodBufferHandler.getColumnRenderBuffers();
|
||||
if (lodBufferContainer != null)
|
||||
{
|
||||
// done to fix a bug with Iris where face culling isn't properly set or reverted in the MC state manager
|
||||
// which causes Sodium to render some water chunks with their normal inverted
|
||||
// https://github.com/IrisShaders/Iris/issues/2582
|
||||
// https://github.com/IrisShaders/Iris/blob/1.21.9/common/src/main/java/net/irisshaders/iris/compat/dh/LodRendererEvents.java#L346
|
||||
GLMC.enableFaceCulling();
|
||||
lodRenderer.render(renderEventParam, opaquePass, lodBufferContainer, profilerWrapper);
|
||||
}
|
||||
|
||||
if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEFAULT)
|
||||
{
|
||||
// Normal LOD rendering
|
||||
|
||||
SortedArraySet<LodBufferContainer> lodBufferContainer = lodBufferHandler.getColumnRenderBuffers();
|
||||
if (lodBufferContainer != null)
|
||||
{
|
||||
for (int lodIndex = 0; lodIndex < lodBufferContainer.size(); lodIndex++)
|
||||
{
|
||||
LodBufferContainer bufferContainer = lodBufferContainer.get(lodIndex);
|
||||
this.setShaderProgramMvmOffset(bufferContainer.minCornerBlockPos, shaderProgram, renderEventParam);
|
||||
|
||||
GLVertexBuffer[] vbos = opaquePass ? bufferContainer.vbos : bufferContainer.vbosTransparent;
|
||||
for (int vboIndex = 0; vboIndex < vbos.length; vboIndex++)
|
||||
{
|
||||
GLVertexBuffer vbo = vbos[vboIndex];
|
||||
if (vbo == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vbo.getVertexCount() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
vbo.bind();
|
||||
shaderProgram.bindVertexBuffer(vbo.getId());
|
||||
GL32.glDrawElements(
|
||||
GL32.GL_TRIANGLES,
|
||||
vbo.getVertexCount(),
|
||||
this.quadIBO.getType(), 0);
|
||||
vbo.unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// basic quad rendering
|
||||
|
||||
TestRenderer.INSTANCE.render();
|
||||
}
|
||||
|
||||
|
||||
//=========================//
|
||||
// debug wireframe cleanup //
|
||||
//=========================//
|
||||
|
||||
if (renderWireframe)
|
||||
{
|
||||
// default back to GL_FILL since all other rendering uses it
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* the MVM offset is needed so LODs can be rendered anywhere in the MC world
|
||||
* without running into floating point percision loss.
|
||||
*/
|
||||
private void setShaderProgramMvmOffset(DhBlockPos pos, IDhApiShaderProgram shaderProgram, RenderParams renderEventParam) throws IllegalStateException
|
||||
{
|
||||
Vec3d camPos = renderEventParam.exactCameraPosition;
|
||||
Vec3f modelPos = new Vec3f(
|
||||
(float) (pos.getX() - camPos.x),
|
||||
(float) (pos.getY() - camPos.y),
|
||||
(float) (pos.getZ() - camPos.z));
|
||||
|
||||
shaderProgram.bind();
|
||||
shaderProgram.setModelOffsetPos(modelPos);
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// API functions //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
/** @return -1 if no frame buffer has been bound yet */
|
||||
public int getActiveFramebufferId() { return this.activeFramebufferId; }
|
||||
|
||||
/** @return -1 if no texture has been bound yet */
|
||||
public int getActiveColorTextureId() { return this.activeColorTextureId; }
|
||||
|
||||
/** @return -1 if no texture has been bound yet */
|
||||
public int getActiveDepthTextureId() { return this.activeDepthTextureId; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
+22
-22
@@ -1,4 +1,4 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
@@ -8,15 +8,15 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShad
|
||||
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.glObject.GLProxy;
|
||||
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.minecraft.IMinecraftGLWrapper;
|
||||
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.awt.*;
|
||||
import java.io.Closeable;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -33,8 +33,8 @@ public class RenderableBoxGroup
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
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);
|
||||
|
||||
@@ -67,9 +67,9 @@ public class RenderableBoxGroup
|
||||
public Consumer<DhApiRenderParam> afterRenderFunc;
|
||||
|
||||
// instance data
|
||||
public InstancedVboContainer instancedVbos = new InstancedVboContainer();
|
||||
public IDhGenericObjectVertexBufferContainer vertexBufferContainer = WRAPPER_FACTORY.createGenericObjectVboContainer();
|
||||
/** double buffering for thread safety and to prevent locking the render thread during update */
|
||||
private InstancedVboContainer altInstancedVbos = new InstancedVboContainer();
|
||||
private IDhGenericObjectVertexBufferContainer altVertexBufferContainer = WRAPPER_FACTORY.createGenericObjectVboContainer();
|
||||
|
||||
|
||||
|
||||
@@ -195,14 +195,14 @@ public class RenderableBoxGroup
|
||||
public void tryUpdateInstancedDataAsync()
|
||||
{
|
||||
// if the alt container is done, swap it in
|
||||
if (this.altInstancedVbos.state == InstancedVboContainer.EState.READY_TO_UPLOAD)
|
||||
if (this.altVertexBufferContainer.getState() == IDhGenericObjectVertexBufferContainer.EState.READY_TO_UPLOAD)
|
||||
{
|
||||
this.altInstancedVbos.uploadDataToGpu();
|
||||
this.altVertexBufferContainer.uploadDataToGpu();
|
||||
|
||||
// swap VBO references for rendering
|
||||
InstancedVboContainer temp = this.instancedVbos;
|
||||
this.instancedVbos = this.altInstancedVbos;
|
||||
this.altInstancedVbos = temp;
|
||||
IDhGenericObjectVertexBufferContainer temp = this.vertexBufferContainer;
|
||||
this.vertexBufferContainer = this.altVertexBufferContainer;
|
||||
this.altVertexBufferContainer = temp;
|
||||
|
||||
this.vertexDataDirty = false;
|
||||
|
||||
@@ -224,15 +224,15 @@ public class RenderableBoxGroup
|
||||
}
|
||||
|
||||
// if the alternate container is already updating, don't double-queue it
|
||||
if (this.altInstancedVbos.state == InstancedVboContainer.EState.UPDATING_DATA)
|
||||
if (this.altVertexBufferContainer.getState() == IDhGenericObjectVertexBufferContainer.EState.UPDATING_DATA)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.altInstancedVbos.state = InstancedVboContainer.EState.UPDATING_DATA;
|
||||
this.altVertexBufferContainer.setState(IDhGenericObjectVertexBufferContainer.EState.UPDATING_DATA);
|
||||
|
||||
|
||||
|
||||
this.altInstancedVbos.tryRunRenderThreadSetup();
|
||||
//this.altInstancedVbos.tryRunRenderThreadSetup();
|
||||
|
||||
// copy over the box list so we can upload without concurrent modification issues
|
||||
this.uploadBoxList.clear();
|
||||
@@ -247,19 +247,19 @@ public class RenderableBoxGroup
|
||||
{
|
||||
try
|
||||
{
|
||||
this.altInstancedVbos.updateVertexData(this.uploadBoxList);
|
||||
this.altVertexBufferContainer.updateVertexData(this.uploadBoxList);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unexpected error updating instanced VBO data for: ["+this+"], error: ["+e.getMessage()+"].", e);
|
||||
this.altInstancedVbos.state = InstancedVboContainer.EState.ERROR;
|
||||
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.altInstancedVbos.state = InstancedVboContainer.EState.NEW;
|
||||
this.altVertexBufferContainer.setState(IDhGenericObjectVertexBufferContainer.EState.NEW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,15 +341,15 @@ public class RenderableBoxGroup
|
||||
//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+"]"; }
|
||||
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()
|
||||
{
|
||||
GLProxy.queueRunningOnRenderThread(() ->
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
|
||||
{
|
||||
this.instancedVbos.close();
|
||||
this.altInstancedVbos.close();
|
||||
this.vertexBufferContainer.close();
|
||||
this.altVertexBufferContainer.close();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* 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.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOApplyShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL43C;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles adding SSAO via {@link SSAOShader} and {@link SSAOApplyShader}. <br><br>
|
||||
*
|
||||
* {@link SSAOShader} - draws the SSAO to a texture. <br>
|
||||
* {@link SSAOApplyShader} - draws the SSAO texture to DH's FrameBuffer. <br>
|
||||
*/
|
||||
public class SSAORenderer
|
||||
{
|
||||
public static SSAORenderer INSTANCE = new SSAORenderer();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int ssaoFramebuffer = -1;
|
||||
|
||||
private int ssaoTexture = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private SSAORenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
SSAOShader.INSTANCE.init();
|
||||
SSAOApplyShader.INSTANCE.init();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.ssaoFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.ssaoFramebuffer);
|
||||
this.ssaoFramebuffer = -1;
|
||||
}
|
||||
|
||||
if (this.ssaoTexture != -1)
|
||||
{
|
||||
GLMC.glDeleteTextures(this.ssaoTexture);
|
||||
this.ssaoTexture = -1;
|
||||
}
|
||||
|
||||
this.ssaoFramebuffer = GL32.glGenFramebuffers();
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
|
||||
|
||||
this.ssaoTexture = GLMC.glGenTextures();
|
||||
{
|
||||
GLMC.glBindTexture(this.ssaoTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (ByteBuffer) null);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||
|
||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(Mat4f projectionMatrix, float partialTicks)
|
||||
{
|
||||
try(GLState state = new GLState())
|
||||
{
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
SSAOShader.INSTANCE.frameBuffer = this.ssaoFramebuffer;
|
||||
SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix);
|
||||
SSAOShader.INSTANCE.render(partialTicks);
|
||||
|
||||
SSAOApplyShader.INSTANCE.ssaoTexture = this.ssaoTexture;
|
||||
SSAOApplyShader.INSTANCE.render(partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
SSAOShader.INSTANCE.free();
|
||||
SSAOApplyShader.INSTANCE.free();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* 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.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Renders a full-screen textured quad to the screen.
|
||||
* Used in composite / deferred rendering (IE fog).
|
||||
*/
|
||||
public class ScreenQuad
|
||||
{
|
||||
public static ScreenQuad INSTANCE = new ScreenQuad();
|
||||
|
||||
private static final float[] box_vertices = {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
1, 1,
|
||||
-1, -1,
|
||||
1, 1,
|
||||
-1, 1,
|
||||
};
|
||||
|
||||
private GLVertexBuffer boxBuffer;
|
||||
private AbstractVertexAttribute va;
|
||||
private boolean init = false;
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private ScreenQuad() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec2Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 2);
|
||||
|
||||
// Framebuffer
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
public void render()
|
||||
{
|
||||
this.init();
|
||||
|
||||
this.boxBuffer.bind();
|
||||
|
||||
this.va.bind();
|
||||
this.va.bindBufferToAllBindingPoints(this.boxBuffer.getId());
|
||||
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(box_vertices.length * Float.BYTES);
|
||||
buffer.asFloatBuffer().put(box_vertices);
|
||||
buffer.rewind();
|
||||
|
||||
this.boxBuffer = new GLVertexBuffer(false);
|
||||
this.boxBuffer.bind();
|
||||
this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EDhApiGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* 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.enums.config.EDhApiGpuUploadMethod;
|
||||
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.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Renders a UV colored quad
|
||||
* to the center of the screen to confirm DH's
|
||||
* apply shader is running correctly
|
||||
*/
|
||||
public class TestRenderer
|
||||
{
|
||||
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
public static final TestRenderer INSTANCE = new TestRenderer();
|
||||
|
||||
// Render a square with uv color
|
||||
private static final float[] VERTICES = {
|
||||
// PosX,Y, ColorR,G,B,A
|
||||
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.4f, -0.4f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.3f, 0.3f, 1.0f, 1.0f, 0.0f, 0.0f,
|
||||
-0.2f, 0.2f, 0.0f, 1.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
|
||||
|
||||
ShaderProgram basicShader;
|
||||
GLVertexBuffer vbo;
|
||||
AbstractVertexAttribute va;
|
||||
boolean init = false;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
private TestRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("init");
|
||||
this.init = true;
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec2Pointer(false));
|
||||
// Color
|
||||
this.va.setVertexAttribute(0, 1, VertexPointer.addVec4Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 6);
|
||||
this.basicShader = new ShaderProgram(
|
||||
"shaders/test/vert.vert",
|
||||
"shaders/test/frag.frag",
|
||||
new String[]{"vPosition", "color"});
|
||||
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(VERTICES.length * Float.BYTES);
|
||||
// Fill buffer with vertices.
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer.asFloatBuffer().put(VERTICES);
|
||||
buffer.rewind();
|
||||
|
||||
this.vbo = new GLVertexBuffer(false);
|
||||
this.vbo.bind();
|
||||
this.vbo.uploadBuffer(buffer, 4, EDhApiGpuUploadMethod.DATA, VERTICES.length * Float.BYTES);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
//region
|
||||
|
||||
public void render()
|
||||
{
|
||||
this.init();
|
||||
|
||||
this.basicShader.bind();
|
||||
this.va.bind();
|
||||
|
||||
this.vbo.bind();
|
||||
this.va.bindBufferToAllBindingPoints(this.vbo.getId());
|
||||
|
||||
// Render the square
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* 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.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.DhFadeShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.FadeApplyShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.VanillaFadeShader;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles fading MC and DH together via {@link VanillaFadeShader} and {@link FadeApplyShader}. <br><br>
|
||||
*
|
||||
* {@link VanillaFadeShader} - draws the Fade to a texture. <br>
|
||||
* {@link FadeApplyShader} - draws the Fade texture to MC's FrameBuffer. <br>
|
||||
*/
|
||||
public class VanillaFadeRenderer
|
||||
{
|
||||
public static VanillaFadeRenderer INSTANCE = new VanillaFadeRenderer();
|
||||
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int fadeFramebuffer = -1;
|
||||
|
||||
private int fadeTexture = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private VanillaFadeRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
VanillaFadeShader.INSTANCE.init();
|
||||
FadeApplyShader.INSTANCE.init();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.fadeFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.fadeFramebuffer);
|
||||
this.fadeFramebuffer = -1;
|
||||
}
|
||||
|
||||
this.fadeFramebuffer = GL32.glGenFramebuffers();
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fadeFramebuffer);
|
||||
|
||||
|
||||
// Applying the fade texture is only needed if MC is drawing to their own frame buffer,
|
||||
// otherwise we can directly render to their texture
|
||||
if (MC_RENDER.mcRendersToFrameBuffer())
|
||||
{
|
||||
if (this.fadeTexture != -1)
|
||||
{
|
||||
GLMC.glDeleteTextures(this.fadeTexture);
|
||||
this.fadeTexture = -1;
|
||||
}
|
||||
|
||||
this.fadeTexture = GL32.glGenTextures();
|
||||
GLMC.glBindTexture(this.fadeTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fadeTexture, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, MC_RENDER.getColorTextureId(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IClientLevelWrapper level)
|
||||
{
|
||||
int depthTextureId = LodRenderer.INSTANCE.getActiveDepthTextureId();
|
||||
if (depthTextureId == -1)
|
||||
{
|
||||
// the renderer hasn't been set up yet
|
||||
// trying to render fading may cause GL errors
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
IProfilerWrapper profiler = MC_CLIENT.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("DH-Vanilla Fade");
|
||||
|
||||
|
||||
try(GLState mcState = new GLState())
|
||||
{
|
||||
profiler.push("Vanilla Fade Generate");
|
||||
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
|
||||
VanillaFadeShader.INSTANCE.frameBuffer = this.fadeFramebuffer;
|
||||
VanillaFadeShader.INSTANCE.setProjectionMatrix(mcModelViewMatrix, mcProjectionMatrix);
|
||||
VanillaFadeShader.INSTANCE.setLevelMaxHeight(level.getMaxHeight());
|
||||
VanillaFadeShader.INSTANCE.render(partialTicks);
|
||||
|
||||
// Applying the fade texture is only needed if MC is drawing to their own frame buffer,
|
||||
// otherwise we can directly render to their texture
|
||||
if (MC_RENDER.mcRendersToFrameBuffer())
|
||||
{
|
||||
profiler.popPush("Vanilla Fade Apply");
|
||||
|
||||
FadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
|
||||
FadeApplyShader.INSTANCE.readFramebuffer = DhFadeShader.INSTANCE.frameBuffer;
|
||||
FadeApplyShader.INSTANCE.drawFramebuffer = MC_RENDER.getTargetFramebuffer();
|
||||
FadeApplyShader.INSTANCE.render(partialTicks);
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unexpected error during fade render, error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
VanillaFadeShader.INSTANCE.free();
|
||||
FadeApplyShader.INSTANCE.free();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.seibel.distanthorizons.core.render;
|
||||
package com.seibel.distanthorizons.core.render.renderer.cullingFrustum;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
package com.seibel.distanthorizons.core.render;
|
||||
package com.seibel.distanthorizons.core.render.renderer.cullingFrustum;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
|
||||
/**
|
||||
* Dummy {@link IDhApiCullingFrustum} that allows everything through. <br>
|
||||
-731
@@ -1,731 +0,0 @@
|
||||
/*
|
||||
* 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.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||
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.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.lwjgl.opengl.ARBInstancedArrays;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Handles rendering generic groups of {@link DhApiRenderableBox}.
|
||||
*
|
||||
* @see IDhApiCustomRenderRegister
|
||||
* @see DhApiRenderableBox
|
||||
*/
|
||||
public class GenericObjectRenderer implements IDhApiCustomRenderRegister
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final ISodiumAccessor SODIUM = ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
private static final DhApiRenderableBoxGroupShading DEFAULT_SHADING = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||
|
||||
/**
|
||||
* Can be used to troubleshoot the renderer.
|
||||
* If enabled several debug objects will render around (0,150,0).
|
||||
*/
|
||||
public static final boolean RENDER_DEBUG_OBJECTS = false;
|
||||
|
||||
|
||||
// rendering setup
|
||||
private boolean init = false;
|
||||
|
||||
private IDhApiGenericObjectShaderProgram instancedShaderProgram;
|
||||
private IDhApiGenericObjectShaderProgram directShaderProgram;
|
||||
private GLVertexBuffer boxVertexBuffer;
|
||||
private GLElementBuffer boxIndexBuffer;
|
||||
|
||||
private boolean instancedRenderingAvailable;
|
||||
private boolean vertexAttribDivisorSupported;
|
||||
private boolean instancedArraysSupported;
|
||||
|
||||
|
||||
|
||||
private final ConcurrentHashMap<Long, RenderableBoxGroup> boxGroupById = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
/** A box from 0,0,0 to 1,1,1 */
|
||||
private static final float[] BOX_VERTICES = {
|
||||
//region
|
||||
// Pos x y z
|
||||
|
||||
// min X, vertical face
|
||||
0, 0, 0,
|
||||
1, 0, 0,
|
||||
1, 1, 0,
|
||||
0, 1, 0,
|
||||
// max X, vertical face
|
||||
0, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 0, 1,
|
||||
0, 0, 1,
|
||||
|
||||
// min Z, vertical face
|
||||
0, 0, 1,
|
||||
0, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 1, 1,
|
||||
// max Z, vertical face
|
||||
1, 0, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 0,
|
||||
1, 0, 0,
|
||||
|
||||
// min Y, horizontal face
|
||||
0, 0, 1,
|
||||
1, 0, 1,
|
||||
1, 0, 0,
|
||||
0, 0, 0,
|
||||
// max Y, horizontal face
|
||||
0, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 0,
|
||||
0, 1, 0,
|
||||
//endregion
|
||||
};
|
||||
|
||||
|
||||
private static final int[] BOX_INDICES = {
|
||||
//region
|
||||
// min X, vertical face
|
||||
2, 1, 0,
|
||||
0, 3, 2,
|
||||
// max X, vertical face
|
||||
6, 5, 4,
|
||||
4, 7, 6,
|
||||
|
||||
// min Z, vertical face
|
||||
10, 9, 8,
|
||||
8, 11, 10,
|
||||
// max Z, vertical face
|
||||
14, 13, 12,
|
||||
12, 15, 14,
|
||||
|
||||
// min Y, horizontal face
|
||||
18, 17, 16,
|
||||
16, 19, 18,
|
||||
// max Y, horizontal face
|
||||
20, 21, 22,
|
||||
22, 23, 20,
|
||||
//endregion
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public GenericObjectRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.init = true;
|
||||
|
||||
|
||||
|
||||
//===================================//
|
||||
// is instanced rendering available? //
|
||||
//===================================//
|
||||
|
||||
this.vertexAttribDivisorSupported = GLProxy.getInstance().vertexAttribDivisorSupported;
|
||||
this.instancedArraysSupported = GLProxy.getInstance().instancedArraysSupported;
|
||||
boolean isMac = (EPlatform.get() == EPlatform.MACOS);
|
||||
this.instancedRenderingAvailable = (this.vertexAttribDivisorSupported || this.instancedArraysSupported) && !isMac;
|
||||
if (!this.instancedRenderingAvailable)
|
||||
{
|
||||
LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow and some effects may be disabled.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
// startup the renderer //
|
||||
//======================//
|
||||
|
||||
this.instancedShaderProgram = new GenericObjectShaderProgram(true);
|
||||
this.directShaderProgram = new GenericObjectShaderProgram(false);
|
||||
|
||||
this.createBuffers();
|
||||
|
||||
if (RENDER_DEBUG_OBJECTS)
|
||||
{
|
||||
this.addGenericDebugObjects();
|
||||
}
|
||||
}
|
||||
private void createBuffers()
|
||||
{
|
||||
// box vertices
|
||||
ByteBuffer boxVerticesBuffer = MemoryUtil.memAlloc(BOX_VERTICES.length * Float.BYTES);
|
||||
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||
boxVerticesBuffer.rewind();
|
||||
this.boxVertexBuffer = new GLVertexBuffer(false);
|
||||
this.boxVertexBuffer.bind();
|
||||
this.boxVertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES);
|
||||
MemoryUtil.memFree(boxVerticesBuffer);
|
||||
|
||||
// box vertex indexes
|
||||
ByteBuffer solidIndexBuffer = MemoryUtil.memAlloc(BOX_INDICES.length * Integer.BYTES);
|
||||
solidIndexBuffer.asIntBuffer().put(BOX_INDICES);
|
||||
solidIndexBuffer.rewind();
|
||||
this.boxIndexBuffer = new GLElementBuffer(false);
|
||||
this.boxIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
this.boxIndexBuffer.bind();
|
||||
MemoryUtil.memFree(solidIndexBuffer);
|
||||
}
|
||||
private void addGenericDebugObjects()
|
||||
{
|
||||
GenericRenderObjectFactory factory = GenericRenderObjectFactory.INSTANCE;
|
||||
|
||||
|
||||
// single giant box
|
||||
IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox(
|
||||
ModInfo.NAME + ":CyanChunkBox",
|
||||
new DhApiRenderableBox(
|
||||
new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16),
|
||||
new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125),
|
||||
EDhApiBlockMaterial.WATER)
|
||||
);
|
||||
singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.add(singleGiantBoxGroup);
|
||||
|
||||
|
||||
// single slender box
|
||||
IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox(
|
||||
ModInfo.NAME + ":GreenBeacon",
|
||||
new DhApiRenderableBox(
|
||||
new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32),
|
||||
new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125),
|
||||
EDhApiBlockMaterial.ILLUMINATED)
|
||||
);
|
||||
singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.add(singleTallBoxGroup);
|
||||
|
||||
|
||||
// absolute box group
|
||||
ArrayList<DhApiRenderableBox> absBoxList = new ArrayList<>();
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
absBoxList.add(new DhApiRenderableBox(
|
||||
new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25),
|
||||
new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()),
|
||||
EDhApiBlockMaterial.LAVA
|
||||
)
|
||||
);
|
||||
}
|
||||
IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(ModInfo.NAME + ":OrangeStairs", absBoxList);
|
||||
this.add(absolutePosBoxGroup);
|
||||
|
||||
|
||||
// relative box group
|
||||
ArrayList<DhApiRenderableBox> relBoxList = new ArrayList<>();
|
||||
for (int i = 0; i < 8; i+=2)
|
||||
{
|
||||
relBoxList.add(new DhApiRenderableBox(
|
||||
new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1),
|
||||
new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()),
|
||||
EDhApiBlockMaterial.METAL
|
||||
)
|
||||
);
|
||||
}
|
||||
IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||
ModInfo.NAME + ":MovingMagentaGroup",
|
||||
new DhApiVec3d(24, 140, 24),
|
||||
relBoxList);
|
||||
relativePosBoxGroup.setPreRenderFunc((event) ->
|
||||
{
|
||||
DhApiVec3d pos = relativePosBoxGroup.getOriginBlockPos();
|
||||
pos.x += event.partialTicks / 2;
|
||||
pos.x %= 32;
|
||||
relativePosBoxGroup.setOriginBlockPos(pos);
|
||||
});
|
||||
this.add(relativePosBoxGroup);
|
||||
|
||||
|
||||
// massive relative box group
|
||||
ArrayList<DhApiRenderableBox> massRelBoxList = new ArrayList<>();
|
||||
for (int x = 0; x < 50*2; x+=2)
|
||||
{
|
||||
for (int z = 0; z < 50*2; z+=2)
|
||||
{
|
||||
massRelBoxList.add(new DhApiRenderableBox(
|
||||
new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z),
|
||||
new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()),
|
||||
EDhApiBlockMaterial.TERRACOTTA
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||
ModInfo.NAME + ":MassRedGroup",
|
||||
new DhApiVec3d(-25, 140, 0),
|
||||
massRelBoxList);
|
||||
massRelativePosBoxGroup.setPreRenderFunc((event) ->
|
||||
{
|
||||
DhApiVec3d blockPos = massRelativePosBoxGroup.getOriginBlockPos();
|
||||
blockPos.y += event.partialTicks / 4;
|
||||
if (blockPos.y > 150f)
|
||||
{
|
||||
blockPos.y = 140f;
|
||||
|
||||
Color newColor = (massRelativePosBoxGroup.get(0).color == Color.RED) ? Color.RED.darker() : Color.RED;
|
||||
massRelativePosBoxGroup.forEach((box) -> { box.color = newColor; });
|
||||
massRelativePosBoxGroup.triggerBoxChange();
|
||||
}
|
||||
|
||||
massRelativePosBoxGroup.setOriginBlockPos(blockPos);
|
||||
});
|
||||
this.add(massRelativePosBoxGroup);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// registration //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void add(IDhApiRenderableBoxGroup iBoxGroup) throws IllegalArgumentException
|
||||
{
|
||||
if (!(iBoxGroup instanceof RenderableBoxGroup))
|
||||
{
|
||||
throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
|
||||
}
|
||||
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
|
||||
|
||||
|
||||
long id = boxGroup.getId();
|
||||
if (this.boxGroupById.containsKey(id))
|
||||
{
|
||||
throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present.");
|
||||
}
|
||||
|
||||
this.boxGroupById.put(id, boxGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDhApiRenderableBoxGroup remove(long id) { return this.boxGroupById.remove(id); }
|
||||
|
||||
public void clear() { this.boxGroupById.clear(); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
/**
|
||||
* @param renderingWithSsao
|
||||
* if true that means this render call is happening before the SSAO pass
|
||||
* and any objects rendered in this pass will have SSAO applied to them.
|
||||
*/
|
||||
public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler, boolean renderingWithSsao)
|
||||
{
|
||||
// render setup //
|
||||
profiler.push("setup");
|
||||
|
||||
this.init();
|
||||
|
||||
boolean useInstancedRendering = this.instancedRenderingAvailable
|
||||
&& Config.Client.Advanced.Graphics.GenericRendering.enableInstancedRendering.get();
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||
|
||||
|
||||
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
|
||||
if (renderWireframe)
|
||||
{
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||
GLMC.disableFaceCulling();
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
GLMC.enableBlend();
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
IDhApiGenericObjectShaderProgram shaderProgram = useInstancedRendering ? this.instancedShaderProgram : this.directShaderProgram;
|
||||
IDhApiGenericObjectShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiGenericObjectShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
shaderProgram.bind(renderEventParam);
|
||||
shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
|
||||
|
||||
this.boxIndexBuffer.bind();
|
||||
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
|
||||
|
||||
// rendering //
|
||||
|
||||
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||
for (RenderableBoxGroup boxGroup : boxList)
|
||||
{
|
||||
// validation //
|
||||
|
||||
// shouldn't happen, but just in case
|
||||
if (boxGroup == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip boxes that shouldn't render this pass
|
||||
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profiler.popPush("render prep");
|
||||
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||
|
||||
// ignore inactive groups
|
||||
if (!boxGroup.active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// allow API users to cancel this object's rendering
|
||||
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||
if (cancelRendering)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// update instanced data if needed
|
||||
if (useInstancedRendering)
|
||||
{
|
||||
boxGroup.tryUpdateInstancedDataAsync();
|
||||
|
||||
// skip groups that haven't been uploaded yet
|
||||
if (boxGroup.instancedVbos.state != InstancedVboContainer.EState.RENDER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// render //
|
||||
|
||||
profiler.popPush("rendering");
|
||||
profiler.push(boxGroup.getResourceLocationNamespace());
|
||||
profiler.push(boxGroup.getResourceLocationPath());
|
||||
if (useInstancedRendering)
|
||||
{
|
||||
this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||
}
|
||||
profiler.pop(); // resource path
|
||||
profiler.pop(); // resource namespace
|
||||
|
||||
boxGroup.postRender(renderEventParam);
|
||||
}
|
||||
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
//==========//
|
||||
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||
|
||||
if (renderWireframe)
|
||||
{
|
||||
// default back to GL_FILL since all other rendering uses it
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
shaderProgram.unbind();
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// instanced rendering //
|
||||
//=====================//
|
||||
//region
|
||||
|
||||
private void renderBoxGroupInstanced(
|
||||
IDhApiGenericObjectShaderProgram shaderProgram, DhApiRenderParam renderEventParam,
|
||||
RenderableBoxGroup boxGroup, Vec3d camPos,
|
||||
IProfilerWrapper profiler)
|
||||
{
|
||||
// update instance data //
|
||||
|
||||
profiler.push("vertex setup");
|
||||
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DEFAULT_SHADING;
|
||||
}
|
||||
|
||||
shaderProgram.fillIndirectUniformData(
|
||||
renderEventParam,
|
||||
shading, boxGroup,
|
||||
camPos);
|
||||
|
||||
|
||||
|
||||
// Bind instance data //
|
||||
profiler.popPush("binding");
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instancedVbos.color);
|
||||
GL32.glEnableVertexAttribArray(1);
|
||||
GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0);
|
||||
this.vertexAttribDivisor(1, 1);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instancedVbos.scale);
|
||||
GL32.glEnableVertexAttribArray(2);
|
||||
this.vertexAttribDivisor(2, 1);
|
||||
GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instancedVbos.chunkPos);
|
||||
GL32.glEnableVertexAttribArray(3);
|
||||
this.vertexAttribDivisor(3, 1);
|
||||
GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instancedVbos.subChunkPos);
|
||||
GL32.glEnableVertexAttribArray(4);
|
||||
this.vertexAttribDivisor(4, 1);
|
||||
GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instancedVbos.material);
|
||||
GL32.glEnableVertexAttribArray(5);
|
||||
this.vertexAttribDivisor(5, 1);
|
||||
GL32.glVertexAttribIPointer(5, 1, GL32.GL_BYTE, Byte.BYTES, 0);
|
||||
|
||||
|
||||
// Draw instanced
|
||||
profiler.popPush("render");
|
||||
if (boxGroup.instancedVbos.uploadedBoxCount > 0)
|
||||
{
|
||||
GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.instancedVbos.uploadedBoxCount);
|
||||
}
|
||||
|
||||
|
||||
// Clean up
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
GL32.glDisableVertexAttribArray(1);
|
||||
GL32.glDisableVertexAttribArray(2);
|
||||
GL32.glDisableVertexAttribArray(3);
|
||||
GL32.glDisableVertexAttribArray(4);
|
||||
GL32.glDisableVertexAttribArray(5);
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
/**
|
||||
* Clean way to handle both {@link GL33#glVertexAttribDivisor} and {@link ARBInstancedArrays#glVertexAttribDivisorARB}
|
||||
* based on which one is supported.
|
||||
*/
|
||||
private void vertexAttribDivisor(int index, int divisor)
|
||||
{
|
||||
if (this.vertexAttribDivisorSupported)
|
||||
{
|
||||
GL33.glVertexAttribDivisor(index, divisor);
|
||||
}
|
||||
else if(this.instancedArraysSupported)
|
||||
{
|
||||
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Instanced rendering isn't supported by this machine. Direct rendering should have been used instead.");
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// direct rendering //
|
||||
//==================//
|
||||
//region
|
||||
|
||||
private void renderBoxGroupDirect(
|
||||
IDhApiGenericObjectShaderProgram shaderProgram,
|
||||
DhApiRenderParam renderEventParam,
|
||||
RenderableBoxGroup boxGroup, Vec3d camPos,
|
||||
IProfilerWrapper profiler)
|
||||
{
|
||||
profiler.popPush("shared uniforms");
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||
}
|
||||
|
||||
shaderProgram.fillSharedDirectUniformData(renderEventParam, shading, boxGroup, camPos);
|
||||
|
||||
for (int i = 0; i < boxGroup.size(); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
DhApiRenderableBox box = boxGroup.get(i);
|
||||
if (box != null)
|
||||
{
|
||||
profiler.popPush("direct uniforms");
|
||||
shaderProgram.fillDirectUniformData(renderEventParam, boxGroup, box, camPos);
|
||||
|
||||
profiler.popPush("render");
|
||||
GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
// Concurrency issue, the list was modified while rendering
|
||||
// this can probably be ignored.
|
||||
// However, if it does become a problem we can add locks to the box group.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
/** @throws IllegalStateException if {@link #init()} function hasn't been called yet */
|
||||
public boolean getInstancedRenderingAvailable() throws IllegalStateException
|
||||
{
|
||||
if (!this.init)
|
||||
{
|
||||
throw new IllegalStateException("GL initialization hasn't been completed.");
|
||||
}
|
||||
|
||||
return this.instancedRenderingAvailable;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// F3 menu //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
public String getVboRenderDebugMenuString()
|
||||
{
|
||||
// get counts
|
||||
int totalGroupCount = this.boxGroupById.size();
|
||||
int totalBoxCount = 0;
|
||||
|
||||
int activeGroupCount = 0;
|
||||
int activeBoxCount = 0;
|
||||
|
||||
for (long key : this.boxGroupById.keySet())
|
||||
{
|
||||
RenderableBoxGroup renderGroup = this.boxGroupById.get(key);
|
||||
if (renderGroup.active)
|
||||
{
|
||||
activeGroupCount++;
|
||||
activeBoxCount += renderGroup.size();
|
||||
}
|
||||
totalBoxCount += renderGroup.size();
|
||||
}
|
||||
|
||||
|
||||
return "Generic Obj #: " + F3Screen.NUMBER_FORMAT.format(activeGroupCount) + "/" + F3Screen.NUMBER_FORMAT.format(totalGroupCount) + ", " +
|
||||
"Cube #: " + F3Screen.NUMBER_FORMAT.format(activeBoxCount) + "/" + F3Screen.NUMBER_FORMAT.format(totalBoxCount);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-231
@@ -1,231 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
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.math.DhApiVec3i;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
public class GenericObjectShaderProgram extends ShaderProgram implements IDhApiGenericObjectShaderProgram
|
||||
{
|
||||
public static final String VERTEX_SHADER_INSTANCED_PATH = "shaders/genericObject/instanced/vert.vert";
|
||||
public static final String VERTEX_SHADER_DIRECT_PATH = "shaders/genericObject/direct/vert.vert";
|
||||
public static final String FRAGMENT_SHADER_INSTANCED_PATH = "shaders/genericObject/instanced/frag.frag";
|
||||
public static final String FRAGMENT_SHADER_DIRECT_PATH = "shaders/genericObject/direct/frag.frag";
|
||||
|
||||
public final AbstractVertexAttribute va;
|
||||
|
||||
|
||||
// shader uniforms
|
||||
private final int directShaderTransformUniform;
|
||||
private final int directShaderColorUniform;
|
||||
|
||||
private final int instancedShaderOffsetChunkUniform;
|
||||
private final int instancedShaderOffsetSubChunkUniform;
|
||||
private final int instancedShaderCameraChunkPosUniform;
|
||||
private final int instancedShaderCameraSubChunkPosUniform;
|
||||
private final int instancedShaderProjectionModelViewMatrixUniform;
|
||||
|
||||
private final int lightMapUniform;
|
||||
private final int skyLightUniform;
|
||||
private final int blockLightUniform;
|
||||
|
||||
private final int northShadingUniform;
|
||||
private final int southShadingUniform;
|
||||
private final int eastShadingUniform;
|
||||
private final int westShadingUniform;
|
||||
private final int topShadingUniform;
|
||||
private final int bottomShadingUniform;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public GenericObjectShaderProgram(boolean useInstancedRendering)
|
||||
{
|
||||
super(
|
||||
useInstancedRendering ? VERTEX_SHADER_INSTANCED_PATH : VERTEX_SHADER_DIRECT_PATH,
|
||||
useInstancedRendering ? FRAGMENT_SHADER_INSTANCED_PATH : FRAGMENT_SHADER_DIRECT_PATH,
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 3);
|
||||
|
||||
this.directShaderTransformUniform = this.tryGetUniformLocation("uTransform");
|
||||
this.directShaderColorUniform = this.tryGetUniformLocation("uColor");
|
||||
|
||||
this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation("uOffsetChunk");
|
||||
this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation("uOffsetSubChunk");
|
||||
this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation("uCameraPosChunk");
|
||||
this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation("uCameraPosSubChunk");
|
||||
this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation("uProjectionMvm");
|
||||
|
||||
this.lightMapUniform = this.getUniformLocation("uLightMap");
|
||||
this.skyLightUniform = this.getUniformLocation("uSkyLight");
|
||||
this.blockLightUniform = this.getUniformLocation("uBlockLight");
|
||||
this.northShadingUniform = this.getUniformLocation("uNorthShading");
|
||||
this.southShadingUniform = this.getUniformLocation("uSouthShading");
|
||||
this.eastShadingUniform = this.getUniformLocation("uEastShading");
|
||||
this.westShadingUniform = this.getUniformLocation("uWestShading");
|
||||
this.topShadingUniform = this.getUniformLocation("uTopShading");
|
||||
this.bottomShadingUniform = this.getUniformLocation("uBottomShading");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public void bind(DhApiRenderParam renderEventParam)
|
||||
{
|
||||
super.bind();
|
||||
this.va.bind();
|
||||
}
|
||||
@Override
|
||||
public void unbind()
|
||||
{
|
||||
super.unbind();
|
||||
this.va.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free()
|
||||
{
|
||||
this.va.free();
|
||||
super.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindVertexBuffer(int vbo) { this.va.bindBufferToAllBindingPoints(vbo); }
|
||||
|
||||
@Override
|
||||
public void fillIndirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||
DhApiVec3d camPos
|
||||
)
|
||||
{
|
||||
Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||
projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||
|
||||
super.bind();
|
||||
|
||||
|
||||
|
||||
|
||||
this.setUniform(this.instancedShaderOffsetChunkUniform,
|
||||
new DhApiVec3i(
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
));
|
||||
this.setUniform(this.instancedShaderOffsetSubChunkUniform,
|
||||
new Vec3f(
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
));
|
||||
|
||||
this.setUniform(this.instancedShaderCameraChunkPosUniform,
|
||||
new DhApiVec3i(
|
||||
LodUtil.getChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getChunkPosFromDouble(camPos.z)
|
||||
));
|
||||
this.setUniform(this.instancedShaderCameraSubChunkPosUniform,
|
||||
new Vec3f(
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.z)
|
||||
));
|
||||
|
||||
this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, projectionMvmMatrix);
|
||||
|
||||
this.setUniform(this.lightMapUniform, ILightMapWrapper.BOUND_INDEX);
|
||||
this.setUniform(this.skyLightUniform, boxGroup.getSkyLight());
|
||||
this.setUniform(this.blockLightUniform, boxGroup.getBlockLight());
|
||||
|
||||
|
||||
this.setUniform(this.northShadingUniform, shading.north);
|
||||
this.setUniform(this.southShadingUniform, shading.south);
|
||||
this.setUniform(this.eastShadingUniform, shading.east);
|
||||
this.setUniform(this.westShadingUniform, shading.west);
|
||||
this.setUniform(this.topShadingUniform, shading.top);
|
||||
this.setUniform(this.bottomShadingUniform, shading.bottom);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void fillSharedDirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||
DhApiVec3d camPos)
|
||||
{
|
||||
|
||||
this.setUniform(this.lightMapUniform, ILightMapWrapper.BOUND_INDEX);
|
||||
this.setUniform(this.skyLightUniform, boxGroup.getSkyLight());
|
||||
this.setUniform(this.blockLightUniform, boxGroup.getBlockLight());
|
||||
|
||||
|
||||
this.setUniform(this.northShadingUniform, shading.north);
|
||||
this.setUniform(this.southShadingUniform, shading.south);
|
||||
this.setUniform(this.eastShadingUniform, shading.east);
|
||||
this.setUniform(this.westShadingUniform, shading.west);
|
||||
this.setUniform(this.topShadingUniform, shading.top);
|
||||
this.setUniform(this.bottomShadingUniform, shading.bottom);
|
||||
|
||||
}
|
||||
|
||||
public void fillDirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box,
|
||||
DhApiVec3d camPos)
|
||||
{
|
||||
Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||
projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(
|
||||
(float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x),
|
||||
(float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y),
|
||||
(float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z));
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(
|
||||
(float) (box.maxPos.x - box.minPos.x),
|
||||
(float) (box.maxPos.y - box.minPos.y),
|
||||
(float) (box.maxPos.z - box.minPos.z)));
|
||||
projectionMvmMatrix.multiply(boxTransform);
|
||||
this.setUniform(this.directShaderTransformUniform, projectionMvmMatrix);
|
||||
|
||||
this.setUniform(this.directShaderColorUniform, box.color);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getId() { return this.id; }
|
||||
|
||||
/** The base DH render program should always render */
|
||||
@Override
|
||||
public boolean overrideThisFrame() { return true; }
|
||||
|
||||
}
|
||||
-193
@@ -1,193 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
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.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* For use by {@link RenderableBoxGroup}
|
||||
*
|
||||
* @see RenderableBoxGroup
|
||||
*/
|
||||
public class InstancedVboContainer implements AutoCloseable
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
|
||||
public int chunkPos = 0;
|
||||
public int subChunkPos = 0;
|
||||
public int scale = 0;
|
||||
public int color = 0;
|
||||
public int material = 0;
|
||||
|
||||
public int[] chunkPosData = new int[0];
|
||||
public float[] subChunkPosData = new float[0];
|
||||
public float[] scalingData = new float[0];
|
||||
public float[] colorData = new float[0];
|
||||
public int[] materialData = new int[0];
|
||||
|
||||
public int uploadedBoxCount = 0;
|
||||
|
||||
public EState state = EState.NEW;
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
// render building/uploading //
|
||||
//===========================//
|
||||
//region
|
||||
|
||||
/** needs to be done on the render thread */
|
||||
public void tryRunRenderThreadSetup()
|
||||
{
|
||||
if (this.chunkPos == 0)
|
||||
{
|
||||
this.chunkPos = GLMC.glGenBuffers();
|
||||
this.subChunkPos = GLMC.glGenBuffers();
|
||||
this.scale = GLMC.glGenBuffers();
|
||||
this.color = GLMC.glGenBuffers();
|
||||
this.material = GLMC.glGenBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateVertexData(List<DhApiRenderableBox> uploadBoxList)
|
||||
{
|
||||
int boxCount = uploadBoxList.size();
|
||||
|
||||
|
||||
// recreate the data arrays if their size is different
|
||||
if (this.uploadedBoxCount != boxCount)
|
||||
{
|
||||
this.uploadedBoxCount = boxCount;
|
||||
|
||||
this.chunkPosData = new int[boxCount * 3]; // 3 elements XYZ
|
||||
this.subChunkPosData = new float[boxCount * 3]; // 3 elements XYZ
|
||||
this.scalingData = new float[boxCount * 3]; // 3 elements XYZ
|
||||
|
||||
this.colorData = new float[boxCount * 4]; // 4 elements, RGBA
|
||||
this.materialData = new int[boxCount];
|
||||
}
|
||||
|
||||
|
||||
// transformation / scaling //
|
||||
for (int i = 0; i < boxCount; i++)
|
||||
{
|
||||
DhApiRenderableBox box = uploadBoxList.get(i);
|
||||
|
||||
int dataIndex = i * 3;
|
||||
|
||||
this.chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x);
|
||||
this.chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y);
|
||||
this.chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z);
|
||||
|
||||
this.subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x);
|
||||
this.subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y);
|
||||
this.subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z);
|
||||
|
||||
this.scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x);
|
||||
this.scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y);
|
||||
this.scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z);
|
||||
}
|
||||
|
||||
|
||||
// colors/materials //
|
||||
for (int i = 0; i < boxCount; i++)
|
||||
{
|
||||
DhApiRenderableBox box = uploadBoxList.get(i);
|
||||
Color color = box.color;
|
||||
int colorIndex = i * 4;
|
||||
this.colorData[colorIndex] = color.getRed() / 255.0f;
|
||||
this.colorData[colorIndex + 1] = color.getGreen() / 255.0f;
|
||||
this.colorData[colorIndex + 2] = color.getBlue() / 255.0f;
|
||||
this.colorData[colorIndex + 3] = color.getAlpha() / 255.0f;
|
||||
|
||||
this.materialData[i] = box.material;
|
||||
}
|
||||
|
||||
this.state = InstancedVboContainer.EState.READY_TO_UPLOAD;
|
||||
}
|
||||
|
||||
public void uploadDataToGpu()
|
||||
{
|
||||
// Upload transformation matrices
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.chunkPos);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.chunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.subChunkPos);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.subChunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.scale);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.scalingData, GL32.GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload colors
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.color);
|
||||
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.colorData, GL32.GL_DYNAMIC_DRAW);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
tryDeleteBuffer(this.chunkPos);
|
||||
tryDeleteBuffer(this.subChunkPos);
|
||||
tryDeleteBuffer(this.scale);
|
||||
tryDeleteBuffer(this.color);
|
||||
tryDeleteBuffer(this.material);
|
||||
}
|
||||
private static void tryDeleteBuffer(int bufferId)
|
||||
{
|
||||
// usually unnecessary, but just in case
|
||||
if (bufferId != 0)
|
||||
{
|
||||
GLMC.glDeleteBuffers(bufferId);
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
public enum EState
|
||||
{
|
||||
NEW,
|
||||
UPDATING_DATA,
|
||||
READY_TO_UPLOAD,
|
||||
RENDER,
|
||||
|
||||
ERROR,
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public abstract class AbstractShaderRenderer
|
||||
{
|
||||
protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
protected ShaderProgram shader;
|
||||
|
||||
protected boolean init = false;
|
||||
|
||||
|
||||
protected AbstractShaderRenderer() {}
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
this.onInit();
|
||||
}
|
||||
|
||||
public void render(float partialTicks)
|
||||
{
|
||||
this.init();
|
||||
|
||||
this.shader.bind();
|
||||
|
||||
this.onApplyUniforms(partialTicks);
|
||||
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
GL32.glViewport(0, 0, width, height);
|
||||
|
||||
this.onRender();
|
||||
|
||||
this.shader.unbind();
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
if (this.shader != null)
|
||||
{
|
||||
this.shader.free();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onInit() {}
|
||||
|
||||
protected void onApplyUniforms(float partialTicks) {}
|
||||
|
||||
protected void onRender() {}
|
||||
}
|
||||
-198
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Copies {@link LodRenderer}'s currently active color and depth texture to Minecraft's framebuffer.
|
||||
*/
|
||||
public class DhApplyShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static DhApplyShader INSTANCE = new DhApplyShader();
|
||||
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
// uniforms
|
||||
public int gDhColorTextureUniform;
|
||||
public int gDepthMapUniform;
|
||||
|
||||
|
||||
|
||||
//=======//
|
||||
// setup //
|
||||
//=======//
|
||||
//region
|
||||
|
||||
private DhApplyShader() { }
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/apply.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// uniform setup
|
||||
this.gDhColorTextureUniform = this.shader.getUniformLocation("gDhColorTexture");
|
||||
this.gDepthMapUniform = this.shader.getUniformLocation("gDhDepthTexture");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks) { }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
if (MC_RENDER.mcRendersToFrameBuffer())
|
||||
{
|
||||
this.renderToFrameBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderToMcTexture();
|
||||
}
|
||||
}
|
||||
private void renderToFrameBuffer()
|
||||
{
|
||||
int targetFrameBuffer = MC_RENDER.getTargetFramebuffer();
|
||||
if (targetFrameBuffer == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try (GLState state = new GLState())
|
||||
{
|
||||
|
||||
GLMC.disableDepthTest();
|
||||
|
||||
// blending isn't needed, we're manually merging the MC and DH textures
|
||||
// Note: this prevents the sun/moon and stars from rendering through transparent LODs,
|
||||
// however this also fixes transparent LODs from glowing when rendered against the sky during the day
|
||||
GLMC.disableBlend();
|
||||
|
||||
// old blending logic in case it's ever needed:
|
||||
//GLMC.enableBlend();
|
||||
//GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
//GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveColorTextureId());
|
||||
GL32.glUniform1i(this.gDhColorTextureUniform, 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId());
|
||||
GL32.glUniform1i(this.gDepthMapUniform, 1);
|
||||
|
||||
// Copy to MC's framebuffer
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, targetFrameBuffer);
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
// everything's been restored, except at this point the MC framebuffer should now be used instead
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, targetFrameBuffer);
|
||||
|
||||
}
|
||||
private void renderToMcTexture()
|
||||
{
|
||||
int targetColorTextureId = MC_RENDER.getColorTextureId();
|
||||
if (targetColorTextureId == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int dhFrameBufferId = LodRenderer.INSTANCE.getActiveFramebufferId();
|
||||
if (dhFrameBufferId == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int mcFrameBufferId = MC_RENDER.getTargetFramebuffer();
|
||||
if (mcFrameBufferId == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
try (GLState state = new GLState())
|
||||
{
|
||||
GLMC.disableDepthTest();
|
||||
|
||||
// blending isn't needed, we're just directly merging the MC and DH textures
|
||||
// Note: this prevents the sun/moon and stars from rendering through transparent LODs,
|
||||
// however this also fixes
|
||||
GLMC.disableBlend();
|
||||
|
||||
// old blending logic in case it's ever needed:
|
||||
//GLMC.enableBlend();
|
||||
//GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
//GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveColorTextureId());
|
||||
GL32.glUniform1i(this.gDhColorTextureUniform, 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId());
|
||||
GL32.glUniform1i(this.gDepthMapUniform, 1);
|
||||
|
||||
|
||||
|
||||
GL32.glFramebufferTexture(GL32.GL_DRAW_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, targetColorTextureId, 0);
|
||||
|
||||
// Copy to MC's texture via MC's framebuffer
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, dhFrameBufferId);
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
// everything's been restored, except at this point the MC framebuffer should now be used instead
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, mcFrameBufferId);
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
-164
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class DhFadeShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static DhFadeShader INSTANCE = new DhFadeShader();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public int frameBuffer = -1;
|
||||
|
||||
private Mat4f inverseDhMvmProjMatrix;
|
||||
|
||||
|
||||
// Uniforms
|
||||
|
||||
/** Inverted Model View Projection matrix */
|
||||
public int uDhInvMvmProj = -1;
|
||||
|
||||
public int uDhDepthTexture = -1;
|
||||
public int uMcColorTexture = -1;
|
||||
public int uDhColorTexture = -1;
|
||||
|
||||
public int uStartFadeBlockDistance = -1;
|
||||
public int uEndFadeBlockDistance = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public DhFadeShader() { }
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/fade/dhFade.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// all uniforms should be tryGet...
|
||||
// because disabling fade can cause the GLSL to optimize out most (if not all) uniforms
|
||||
|
||||
// near fade
|
||||
this.uDhInvMvmProj = this.shader.tryGetUniformLocation("uDhInvMvmProj");
|
||||
|
||||
this.uDhDepthTexture = this.shader.tryGetUniformLocation("uDhDepthTexture");
|
||||
this.uMcColorTexture = this.shader.tryGetUniformLocation("uMcColorTexture");
|
||||
this.uDhColorTexture = this.shader.tryGetUniformLocation("uDhColorTexture");
|
||||
|
||||
this.uStartFadeBlockDistance = this.shader.tryGetUniformLocation("uStartFadeBlockDistance");
|
||||
this.uEndFadeBlockDistance = this.shader.tryGetUniformLocation("uEndFadeBlockDistance");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
this.shader.setUniform(this.uDhInvMvmProj, this.inverseDhMvmProjMatrix);
|
||||
|
||||
|
||||
float dhFarClipDistance = RenderUtil.getFarClipPlaneDistanceInBlocks();
|
||||
float fadeStartDistance = dhFarClipDistance * 0.5f;
|
||||
float fadeEndDistance = dhFarClipDistance * 0.9f;
|
||||
|
||||
this.shader.setUniform(this.uStartFadeBlockDistance, fadeStartDistance);
|
||||
this.shader.setUniform(this.uEndFadeBlockDistance, fadeEndDistance);
|
||||
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix)
|
||||
{
|
||||
Mat4f dhProjectionMatrix = RenderUtil.createLodProjectionMatrix(mcProjectionMatrix);
|
||||
Mat4f dhModelViewMatrix = RenderUtil.createLodModelViewMatrix(mcModelViewMatrix);
|
||||
|
||||
Mat4f inverseDhModelViewProjectionMatrix = new Mat4f(dhProjectionMatrix);
|
||||
inverseDhModelViewProjectionMatrix.multiply(dhModelViewMatrix);
|
||||
inverseDhModelViewProjectionMatrix.invert();
|
||||
this.inverseDhMvmProjMatrix = inverseDhModelViewProjectionMatrix;
|
||||
}
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
int depthTextureId = LodRenderer.INSTANCE.getActiveDepthTextureId();
|
||||
int colorTextureId = LodRenderer.INSTANCE.getActiveColorTextureId();
|
||||
|
||||
if (depthTextureId == -1
|
||||
|| colorTextureId == -1)
|
||||
{
|
||||
// the renderer is currently being re-built and/or inactive,
|
||||
// we don't need to/can't render fading
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.frameBuffer);
|
||||
GLMC.disableScissorTest();
|
||||
GLMC.disableDepthTest();
|
||||
GLMC.disableBlend();
|
||||
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(depthTextureId);
|
||||
GL32.glUniform1i(this.uDhDepthTexture, 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(MC_RENDER.getColorTextureId());
|
||||
GL32.glUniform1i(this.uMcColorTexture, 1);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE2);
|
||||
GLMC.glBindTexture(colorTextureId);
|
||||
GL32.glUniform1i(this.uDhColorTexture, 2);
|
||||
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
|
||||
}
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.VanillaFadeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Draws the Fade texture onto Minecraft's FrameBuffer. <br><br>
|
||||
*
|
||||
* See Also: <br>
|
||||
* {@link VanillaFadeRenderer} - Parent to this shader. <br>
|
||||
* {@link VanillaFadeShader} - draws the Fade texture. <br>
|
||||
*/
|
||||
public class FadeApplyShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static FadeApplyShader INSTANCE = new FadeApplyShader();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
|
||||
public int fadeTexture;
|
||||
|
||||
public int readFramebuffer;
|
||||
public int drawFramebuffer;
|
||||
|
||||
// uniforms
|
||||
public int uFadeColorTextureUniform = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/fade/apply.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// uniform setup
|
||||
this.uFadeColorTextureUniform = this.shader.getUniformLocation("uFadeColorTextureUniform");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(this.fadeTexture);
|
||||
GL32.glUniform1i(this.uFadeColorTextureUniform, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLMC.disableBlend();
|
||||
|
||||
// Depth testing must be disabled otherwise this application shader won't apply anything.
|
||||
// setting this isn't necessary in vanilla, but some mods may change this, requiring it to be set manually,
|
||||
// it should be automatically restored after rendering is complete.
|
||||
GLMC.disableDepthTest();
|
||||
|
||||
|
||||
// apply the rendered Fade to Minecraft's framebuffer
|
||||
GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, this.readFramebuffer);
|
||||
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, this.drawFramebuffer);
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
|
||||
GLMC.enableDepthTest();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.FogRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Draws the Fog texture onto DH's FrameBuffer. <br><br>
|
||||
*
|
||||
* See Also: <br>
|
||||
* {@link FogRenderer} - Parent to this shader. <br>
|
||||
* {@link FogShader} - draws the Fog texture. <br>
|
||||
*/
|
||||
public class FogApplyShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static FogApplyShader INSTANCE = new FogApplyShader();
|
||||
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public int fogTexture;
|
||||
|
||||
// uniforms
|
||||
public int colorTextureUniform;
|
||||
public int depthTextureUniform;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/fog/apply.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// uniform setup
|
||||
this.colorTextureUniform = this.shader.getUniformLocation("uColorTexture");
|
||||
this.depthTextureUniform = this.shader.getUniformLocation("uDepthTexture");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(this.fogTexture);
|
||||
GL32.glUniform1i(this.colorTextureUniform, 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId());
|
||||
GL32.glUniform1i(this.depthTextureUniform, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLMC.enableBlend();
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Depth testing must be disabled otherwise this application shader won't apply anything.
|
||||
// setting this isn't necessary in vanilla, but some mods may change this, requiring it to be set manually,
|
||||
// it should be automatically restored after rendering is complete.
|
||||
GLMC.disableDepthTest();
|
||||
|
||||
|
||||
// apply the rendered Fog to DH's framebuffer
|
||||
GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, FogShader.INSTANCE.frameBuffer);
|
||||
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, LodRenderer.INSTANCE.getActiveFramebufferId());
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
|
||||
GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
}
|
||||
-286
@@ -1,286 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogColorMode;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMixMode;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class FogShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static final FogShader INSTANCE = new FogShader();
|
||||
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
|
||||
public int frameBuffer;
|
||||
|
||||
private Mat4f inverseMvmProjMatrix;
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// Uniforms //
|
||||
//==========//
|
||||
|
||||
public int uDepthMap;
|
||||
/** Inverted Model View Projection matrix */
|
||||
public int uInvMvmProj;
|
||||
|
||||
// fog uniforms
|
||||
public int uFogColor;
|
||||
public int uFogScale;
|
||||
public int uFogVerticalScale;
|
||||
public int uFogDebugMode;
|
||||
public int uFogFalloffType;
|
||||
|
||||
// far fog
|
||||
public int uFarFogStart;
|
||||
public int uFarFogLength;
|
||||
public int uFarFogMin;
|
||||
public int uFarFogRange;
|
||||
public int uFarFogDensity;
|
||||
|
||||
// height fog
|
||||
public int uHeightFogStart;
|
||||
public int uHeightFogLength;
|
||||
public int uHeightFogMin;
|
||||
public int uHeightFogRange;
|
||||
public int uHeightFogDensity;
|
||||
|
||||
public int uHeightFogEnabled;
|
||||
public int uHeightFogFalloffType;
|
||||
public int uHeightBasedOnCamera;
|
||||
public int uHeightFogBaseHeight;
|
||||
public int uHeightFogAppliesUp;
|
||||
public int uHeightFogAppliesDown;
|
||||
public int uUseSphericalFog;
|
||||
public int uHeightFogMixingMode;
|
||||
public int uCameraBlockYPos;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public FogShader() { }
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/fog/fog.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// all uniforms should be tryGet...
|
||||
// because disabling fog can cause the GLSL to optimize out most (if not all) uniforms
|
||||
|
||||
this.uDepthMap = this.shader.getUniformLocation("uDepthMap");
|
||||
this.uInvMvmProj = this.shader.getUniformLocation("uInvMvmProj");
|
||||
|
||||
// Fog uniforms
|
||||
this.uFogScale = this.shader.getUniformLocation("uFogScale");
|
||||
this.uFogVerticalScale = this.shader.getUniformLocation("uFogVerticalScale");
|
||||
this.uFogColor = this.shader.getUniformLocation("uFogColor");
|
||||
this.uFogDebugMode = this.shader.getUniformLocation("uFogDebugMode");
|
||||
this.uFogFalloffType = this.shader.getUniformLocation("uFogFalloffType");
|
||||
|
||||
// fog config
|
||||
this.uFarFogStart = this.shader.getUniformLocation("uFarFogStart");
|
||||
this.uFarFogLength = this.shader.getUniformLocation("uFarFogLength");
|
||||
this.uFarFogMin = this.shader.getUniformLocation("uFarFogMin");
|
||||
this.uFarFogRange = this.shader.getUniformLocation("uFarFogRange");
|
||||
this.uFarFogDensity = this.shader.getUniformLocation("uFarFogDensity");
|
||||
|
||||
// height fog
|
||||
this.uHeightFogStart = this.shader.getUniformLocation("uHeightFogStart");
|
||||
this.uHeightFogLength = this.shader.getUniformLocation("uHeightFogLength");
|
||||
this.uHeightFogMin = this.shader.getUniformLocation("uHeightFogMin");
|
||||
this.uHeightFogRange = this.shader.getUniformLocation("uHeightFogRange");
|
||||
this.uHeightFogDensity = this.shader.getUniformLocation("uHeightFogDensity");
|
||||
|
||||
this.uHeightFogEnabled = this.shader.getUniformLocation("uHeightFogEnabled");
|
||||
this.uHeightFogFalloffType = this.shader.getUniformLocation("uHeightFogFalloffType");
|
||||
this.uHeightBasedOnCamera = this.shader.getUniformLocation("uHeightBasedOnCamera");
|
||||
this.uHeightFogBaseHeight = this.shader.getUniformLocation("uHeightFogBaseHeight");
|
||||
this.uHeightFogAppliesUp = this.shader.getUniformLocation("uHeightFogAppliesUp");
|
||||
this.uHeightFogAppliesDown = this.shader.getUniformLocation("uHeightFogAppliesDown");
|
||||
this.uUseSphericalFog = this.shader.getUniformLocation("uUseSphericalFog");
|
||||
this.uHeightFogMixingMode = this.shader.getUniformLocation("uHeightFogMixingMode");
|
||||
this.uCameraBlockYPos = this.shader.getUniformLocation("uCameraBlockYPos");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
int lodDrawDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get() * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
|
||||
|
||||
if (this.inverseMvmProjMatrix != null)
|
||||
{
|
||||
this.shader.setUniform(this.uInvMvmProj, this.inverseMvmProjMatrix);
|
||||
}
|
||||
|
||||
|
||||
// Fog uniforms
|
||||
this.shader.setUniform(this.uFogColor, this.getFogColor(partialTicks));
|
||||
this.shader.setUniform(this.uFogScale, 1.f / lodDrawDistance);
|
||||
this.shader.setUniform(this.uFogVerticalScale, 1.f / MC.getWrappedClientLevel().getMaxHeight());
|
||||
// only used for debugging
|
||||
this.shader.setUniform(this.uFogDebugMode, 0); // 1 = render everything with fog color // 7 = use debug rendering
|
||||
this.shader.setUniform(this.uFogFalloffType, Config.Client.Advanced.Graphics.Fog.farFogFalloff.get().value);
|
||||
|
||||
|
||||
// fog config
|
||||
float farFogStart = Config.Client.Advanced.Graphics.Fog.farFogStart.get();
|
||||
float farFogEnd = Config.Client.Advanced.Graphics.Fog.farFogEnd.get();
|
||||
float farFogMin = Config.Client.Advanced.Graphics.Fog.farFogMin.get();
|
||||
float farFogMax = Config.Client.Advanced.Graphics.Fog.farFogMax.get();
|
||||
float farFogDensity = Config.Client.Advanced.Graphics.Fog.farFogDensity.get();
|
||||
|
||||
// override fog if underwater
|
||||
if (MC_RENDER.isFogStateSpecial())
|
||||
{
|
||||
// hide everything behind fog
|
||||
farFogStart = 0.0f;
|
||||
farFogEnd = 0.0f;
|
||||
}
|
||||
|
||||
this.shader.setUniform(this.uFarFogStart, farFogStart);
|
||||
this.shader.setUniform(this.uFarFogLength, farFogEnd - farFogStart);
|
||||
this.shader.setUniform(this.uFarFogMin, farFogMin);
|
||||
this.shader.setUniform(this.uFarFogRange, farFogMax - farFogMin);
|
||||
this.shader.setUniform(this.uFarFogDensity, farFogDensity);
|
||||
|
||||
|
||||
// height config
|
||||
EDhApiHeightFogMixMode heightFogMixingMode = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMixMode.get();
|
||||
boolean heightFogEnabled = heightFogMixingMode != EDhApiHeightFogMixMode.SPHERICAL && heightFogMixingMode != EDhApiHeightFogMixMode.CYLINDRICAL;
|
||||
boolean useSphericalFog = heightFogMixingMode == EDhApiHeightFogMixMode.SPHERICAL;
|
||||
EDhApiHeightFogDirection heightFogCameraDirection = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDirection.get();
|
||||
|
||||
float heightFogStart = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogStart.get();
|
||||
float heightFogEnd = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogEnd.get();
|
||||
float heightFogMin = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMin.get();
|
||||
float heightFogMax = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMax.get();
|
||||
float heightFogDensity = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDensity.get();
|
||||
|
||||
this.shader.setUniform(this.uHeightFogStart, heightFogStart);
|
||||
this.shader.setUniform(this.uHeightFogLength, heightFogEnd - heightFogStart);
|
||||
this.shader.setUniform(this.uHeightFogMin, heightFogMin);
|
||||
this.shader.setUniform(this.uHeightFogRange, heightFogMax - heightFogMin);
|
||||
this.shader.setUniform(this.uHeightFogDensity, heightFogDensity);
|
||||
|
||||
|
||||
this.shader.setUniform(this.uHeightFogEnabled, heightFogEnabled);
|
||||
this.shader.setUniform(this.uHeightFogFalloffType, Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogFalloff.get().value);
|
||||
this.shader.setUniform(this.uHeightFogBaseHeight, Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogBaseHeight.get());
|
||||
this.shader.setUniform(this.uHeightBasedOnCamera, heightFogCameraDirection.basedOnCamera);
|
||||
this.shader.setUniform(this.uHeightFogAppliesUp, heightFogCameraDirection.fogAppliesUp);
|
||||
this.shader.setUniform(this.uHeightFogAppliesDown, heightFogCameraDirection.fogAppliesDown);
|
||||
this.shader.setUniform(this.uUseSphericalFog, useSphericalFog);
|
||||
this.shader.setUniform(this.uHeightFogMixingMode, heightFogMixingMode.value);
|
||||
this.shader.setUniform(this.uCameraBlockYPos, (float)MC_RENDER.getCameraExactPosition().y);
|
||||
|
||||
}
|
||||
private Color getFogColor(float partialTicks)
|
||||
{
|
||||
Color fogColor;
|
||||
|
||||
if (Config.Client.Advanced.Graphics.Fog.colorMode.get() == EDhApiFogColorMode.USE_SKY_COLOR)
|
||||
{
|
||||
fogColor = MC_RENDER.getSkyColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
fogColor = MC_RENDER.getFogColor(partialTicks);
|
||||
}
|
||||
|
||||
return fogColor;
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(Mat4f projectionMatrix)
|
||||
{
|
||||
this.inverseMvmProjMatrix = new Mat4f(projectionMatrix);
|
||||
this.inverseMvmProjMatrix.invert();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.frameBuffer);
|
||||
GLMC.disableScissorTest();
|
||||
GLMC.disableDepthTest();
|
||||
GLMC.disableBlend();
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId());
|
||||
GL32.glUniform1i(this.uDepthMap, 0);
|
||||
|
||||
// this is necessary for MC 1.16 (IE Legacy OpenGL)
|
||||
// otherwise the framebuffer isn't cleared correctly and the fog smears across the screen
|
||||
if (MC_RENDER.runningLegacyOpenGL())
|
||||
{
|
||||
// in another part of the DH code we set the fog color to opaque, here it needs to be transparent
|
||||
float[] clearColorValues = new float[4];
|
||||
GL32.glGetFloatv(GL32.GL_COLOR_CLEAR_VALUE, clearColorValues);
|
||||
GL32.glClearColor(clearColorValues[0], clearColorValues[1], clearColorValues[2], 0.0f);
|
||||
|
||||
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
|
||||
}
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.SSAORenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Draws the SSAO texture onto DH's FrameBuffer. <br><br>
|
||||
*
|
||||
* See Also: <br>
|
||||
* {@link SSAORenderer} - Parent to this shader. <br>
|
||||
* {@link SSAOShader} - draws the SSAO texture. <br>
|
||||
*/
|
||||
public class SSAOApplyShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static SSAOApplyShader INSTANCE = new SSAOApplyShader();
|
||||
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public int ssaoTexture;
|
||||
|
||||
// uniforms
|
||||
public int gSSAOMapUniform;
|
||||
public int gDepthMapUniform;
|
||||
public int gViewSizeUniform;
|
||||
public int gBlurRadiusUniform;
|
||||
public int gNearUniform;
|
||||
public int gFarUniform;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/ssao/apply.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// uniform setup
|
||||
this.gSSAOMapUniform = this.shader.getUniformLocation("gSSAOMap");
|
||||
this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap");
|
||||
this.gViewSizeUniform = this.shader.tryGetUniformLocation("gViewSize");
|
||||
this.gBlurRadiusUniform = this.shader.tryGetUniformLocation("gBlurRadius");
|
||||
this.gNearUniform = this.shader.tryGetUniformLocation("gNear");
|
||||
this.gFarUniform = this.shader.tryGetUniformLocation("gFar");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId());
|
||||
GL32.glUniform1i(this.gDepthMapUniform, 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(this.ssaoTexture);
|
||||
GL32.glUniform1i(this.gSSAOMapUniform, 1);
|
||||
|
||||
GL32.glUniform1i(this.gBlurRadiusUniform, 2);
|
||||
|
||||
if (this.gViewSizeUniform >= 0)
|
||||
{
|
||||
GL32.glUniform2f(this.gViewSizeUniform,
|
||||
MC_RENDER.getTargetFramebufferViewportWidth(),
|
||||
MC_RENDER.getTargetFramebufferViewportHeight());
|
||||
}
|
||||
|
||||
if (this.gNearUniform >= 0)
|
||||
{
|
||||
GL32.glUniform1f(this.gNearUniform,
|
||||
RenderUtil.getNearClipPlaneInBlocks());
|
||||
}
|
||||
|
||||
if (this.gFarUniform >= 0)
|
||||
{
|
||||
float farClipPlane = RenderUtil.getFarClipPlaneDistanceInBlocks();
|
||||
GL32.glUniform1f(this.gFarUniform, farClipPlane);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLMC.enableBlend();
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_ZERO, GL32.GL_SRC_ALPHA, GL32.GL_ZERO, GL32.GL_ONE);
|
||||
|
||||
// Depth testing must be disabled otherwise this application shader won't apply anything.
|
||||
// setting this isn't necessary in vanilla, but some mods may change this, requiring it to be set manually,
|
||||
// it should be automatically restored after rendering is complete.
|
||||
GLMC.disableDepthTest();
|
||||
|
||||
// apply the rendered SSAO to the LODs
|
||||
GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, SSAOShader.INSTANCE.frameBuffer);
|
||||
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, LodRenderer.INSTANCE.getActiveFramebufferId());
|
||||
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
|
||||
}
|
||||
}
|
||||
-143
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.SSAORenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.NumberUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* Draws the SSAO to a texture. <br><br>
|
||||
*
|
||||
* See Also: <br>
|
||||
* {@link SSAORenderer} - Parent to this shader. <br>
|
||||
* {@link SSAOApplyShader} - draws the SSAO texture to DH's FrameBuffer. <br>
|
||||
*/
|
||||
public class SSAOShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static SSAOShader INSTANCE = new SSAOShader();
|
||||
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public int frameBuffer;
|
||||
|
||||
private Mat4f projection;
|
||||
private Mat4f invertedProjection;
|
||||
|
||||
|
||||
// uniforms
|
||||
public int uProj;
|
||||
public int uInvProj;
|
||||
public int uSampleCount;
|
||||
public int uRadius;
|
||||
public int uStrength;
|
||||
public int uMinLight;
|
||||
public int uBias;
|
||||
public int uDepthMap;
|
||||
public int uFadeDistanceInBlocks;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/ssao/ao.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// uniform setup
|
||||
this.uProj = this.shader.getUniformLocation("uProj");
|
||||
this.uInvProj = this.shader.getUniformLocation("uInvProj");
|
||||
this.uSampleCount = this.shader.getUniformLocation("uSampleCount");
|
||||
this.uRadius = this.shader.getUniformLocation("uRadius");
|
||||
this.uStrength = this.shader.getUniformLocation("uStrength");
|
||||
this.uMinLight = this.shader.getUniformLocation("uMinLight");
|
||||
this.uBias = this.shader.getUniformLocation("uBias");
|
||||
this.uDepthMap = this.shader.getUniformLocation("uDepthMap");
|
||||
this.uFadeDistanceInBlocks = this.shader.getUniformLocation("uFadeDistanceInBlocks");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
public void setProjectionMatrix(Mat4f projectionMatrix)
|
||||
{
|
||||
this.projection = projectionMatrix;
|
||||
|
||||
this.invertedProjection = new Mat4f(projectionMatrix);
|
||||
this.invertedProjection.invert();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
this.shader.setUniform(this.uProj, this.projection);
|
||||
|
||||
this.shader.setUniform(this.uInvProj, this.invertedProjection);
|
||||
|
||||
this.shader.setUniform(this.uSampleCount, 6);
|
||||
this.shader.setUniform(this.uRadius, 4.0f);
|
||||
this.shader.setUniform(this.uStrength, 0.2f);
|
||||
this.shader.setUniform(this.uMinLight, 0.25f);
|
||||
this.shader.setUniform(this.uBias, 0.02f);
|
||||
this.shader.setUniform(this.uFadeDistanceInBlocks, 1_600.0f);
|
||||
|
||||
GL32.glUniform1i(this.uDepthMap, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.frameBuffer);
|
||||
GLMC.disableScissorTest();
|
||||
GLMC.disableDepthTest();
|
||||
GLMC.disableBlend();
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(LodRenderer.INSTANCE.getActiveDepthTextureId());
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
}
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* 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.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class VanillaFadeShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static VanillaFadeShader INSTANCE = new VanillaFadeShader();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
public int frameBuffer = -1;
|
||||
|
||||
private Mat4f inverseMcMvmProjMatrix;
|
||||
private Mat4f inverseDhMvmProjMatrix;
|
||||
private float levelMaxHeight;
|
||||
|
||||
|
||||
// Uniforms
|
||||
public int uMcDepthTexture = -1;
|
||||
public int uDhDepthTexture = -1;
|
||||
public int uCombinedMcDhColorTexture = -1;
|
||||
public int uDhColorTexture = -1;
|
||||
|
||||
/** Inverted Model View Projection matrix */
|
||||
public int uDhInvMvmProj = -1;
|
||||
public int uMcInvMvmProj = -1;
|
||||
|
||||
public int uStartFadeBlockDistance = -1;
|
||||
public int uEndFadeBlockDistance = -1;
|
||||
public int uMaxLevelHeight = -1;
|
||||
|
||||
public int uOnlyRenderLods = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public VanillaFadeShader() { }
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/quadApply.vert",
|
||||
"shaders/fade/vanillaFade.frag",
|
||||
"vPosition"
|
||||
);
|
||||
|
||||
// all uniforms should be tryGet...
|
||||
// because disabling fade can cause the GLSL to optimize out most (if not all) uniforms
|
||||
|
||||
// near fade
|
||||
this.uDhInvMvmProj = this.shader.tryGetUniformLocation("uDhInvMvmProj");
|
||||
this.uMcInvMvmProj = this.shader.tryGetUniformLocation("uMcInvMvmProj");
|
||||
|
||||
this.uMcDepthTexture = this.shader.tryGetUniformLocation("uMcDepthTexture");
|
||||
this.uDhDepthTexture = this.shader.tryGetUniformLocation("uDhDepthTexture");
|
||||
this.uCombinedMcDhColorTexture = this.shader.tryGetUniformLocation("uCombinedMcDhColorTexture");
|
||||
this.uDhColorTexture = this.shader.tryGetUniformLocation("uDhColorTexture");
|
||||
|
||||
this.uStartFadeBlockDistance = this.shader.tryGetUniformLocation("uStartFadeBlockDistance");
|
||||
this.uEndFadeBlockDistance = this.shader.tryGetUniformLocation("uEndFadeBlockDistance");
|
||||
this.uMaxLevelHeight = this.shader.tryGetUniformLocation("uMaxLevelHeight");
|
||||
|
||||
this.uOnlyRenderLods = this.shader.tryGetUniformLocation("uOnlyRenderLods");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// render prep //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
this.shader.setUniform(this.uMcInvMvmProj, this.inverseMcMvmProjMatrix);
|
||||
this.shader.setUniform(this.uDhInvMvmProj, this.inverseDhMvmProjMatrix);
|
||||
|
||||
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocks();
|
||||
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
dhNearClipDistance += 16f;
|
||||
|
||||
// measured in blocks
|
||||
// these multipliers in James' tests should provide a fairly smooth transition
|
||||
// without having underdraw issues
|
||||
float fadeStartDistance = dhNearClipDistance * 1.5f;
|
||||
float fadeEndDistance = dhNearClipDistance * 1.9f;
|
||||
|
||||
this.shader.setUniform(this.uStartFadeBlockDistance, fadeStartDistance);
|
||||
this.shader.setUniform(this.uEndFadeBlockDistance, fadeEndDistance);
|
||||
|
||||
this.shader.setUniform(this.uMaxLevelHeight, this.levelMaxHeight);
|
||||
|
||||
this.shader.setUniform(this.uOnlyRenderLods, Config.Client.Advanced.Debugging.lodOnlyMode.get());
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix)
|
||||
{
|
||||
Mat4f inverseMcModelViewProjectionMatrix = new Mat4f(mcProjectionMatrix);
|
||||
inverseMcModelViewProjectionMatrix.multiply(mcModelViewMatrix);
|
||||
inverseMcModelViewProjectionMatrix.invert();
|
||||
this.inverseMcMvmProjMatrix = inverseMcModelViewProjectionMatrix;
|
||||
|
||||
|
||||
Mat4f dhProjectionMatrix = RenderUtil.createLodProjectionMatrix(mcProjectionMatrix);
|
||||
Mat4f dhModelViewMatrix = RenderUtil.createLodModelViewMatrix(mcModelViewMatrix);
|
||||
|
||||
Mat4f inverseDhModelViewProjectionMatrix = new Mat4f(dhProjectionMatrix);
|
||||
inverseDhModelViewProjectionMatrix.multiply(dhModelViewMatrix);
|
||||
inverseDhModelViewProjectionMatrix.invert();
|
||||
this.inverseDhMvmProjMatrix = inverseDhModelViewProjectionMatrix;
|
||||
}
|
||||
public void setLevelMaxHeight(int levelMaxHeight) { this.levelMaxHeight = levelMaxHeight; }
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
int depthTextureId = LodRenderer.INSTANCE.getActiveDepthTextureId();
|
||||
int colorTextureId = LodRenderer.INSTANCE.getActiveColorTextureId();
|
||||
|
||||
if (depthTextureId == -1
|
||||
|| colorTextureId == -1)
|
||||
{
|
||||
// the renderer is currently being re-built and/or inactive,
|
||||
// we don't need to/can't render fading
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.frameBuffer);
|
||||
GLMC.disableScissorTest();
|
||||
GLMC.disableDepthTest();
|
||||
GLMC.disableBlend();
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GLMC.glBindTexture(MC_RENDER.getDepthTextureId());
|
||||
GL32.glUniform1i(this.uMcDepthTexture, 0);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GLMC.glBindTexture(depthTextureId);
|
||||
GL32.glUniform1i(this.uDhDepthTexture, 1);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE2);
|
||||
GLMC.glBindTexture(MC_RENDER.getColorTextureId());
|
||||
GL32.glUniform1i(this.uCombinedMcDhColorTexture, 2);
|
||||
|
||||
GLMC.glActiveTexture(GL32.GL_TEXTURE3);
|
||||
GLMC.glBindTexture(colorTextureId);
|
||||
GL32.glUniform1i(this.uDhColorTexture, 3);
|
||||
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
|
||||
}
|
||||
-181
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* 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.vertexFormat;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
|
||||
/**
|
||||
* This is used to represent a single vertex
|
||||
* stored in GPU memory,
|
||||
* <p>
|
||||
* A (almost) exact copy of Minecraft's
|
||||
* VertexFormat class, several methods
|
||||
* were commented out since we didn't need them.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 12-9-2021
|
||||
*/
|
||||
public class LodVertexFormat
|
||||
{
|
||||
private final ImmutableList<LodVertexFormatElement> elements;
|
||||
private final IntList offsets = new IntArrayList();
|
||||
private final int byteSize;
|
||||
|
||||
public LodVertexFormat(ImmutableList<LodVertexFormatElement> elementList)
|
||||
{
|
||||
this.elements = elementList;
|
||||
int i = 0;
|
||||
|
||||
for (LodVertexFormatElement LodVertexFormatElement : elementList)
|
||||
{
|
||||
this.offsets.add(i);
|
||||
i += LodVertexFormatElement.getByteSize();
|
||||
}
|
||||
|
||||
this.byteSize = i;
|
||||
}
|
||||
|
||||
public int getByteSize()
|
||||
{
|
||||
return this.byteSize;
|
||||
}
|
||||
|
||||
public ImmutableList<LodVertexFormatElement> getElements()
|
||||
{
|
||||
return this.elements;
|
||||
}
|
||||
|
||||
|
||||
// Forge added method
|
||||
public int getOffset(int index)
|
||||
{
|
||||
return offsets.getInt(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "format: " + this.elements.size() + " elements: " + this.elements.stream().map(Object::toString).collect(Collectors.joining(" "));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
LodVertexFormat vertexFormat = (LodVertexFormat) obj;
|
||||
return this.byteSize == vertexFormat.byteSize && this.elements.equals(vertexFormat.elements);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.elements.hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* not currently needed setupBufferState()
|
||||
public void setupBufferState(long p_227892_1_)
|
||||
{
|
||||
if (!RenderSystem.isOnRenderThread())
|
||||
{
|
||||
RenderSystem.recordRenderCall(() ->
|
||||
{
|
||||
this.setupBufferState(p_227892_1_);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = this.getVertexSize();
|
||||
List<LodVertexFormatElement> list = this.getElements();
|
||||
|
||||
for (int j = 0; j < list.size(); ++j)
|
||||
{
|
||||
list.get(j).setupBufferState(p_227892_1_ + this.offsets.getInt(j), i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* not currently needed clearBufferState()
|
||||
public void clearBufferState()
|
||||
{
|
||||
if (!RenderSystem.isOnRenderThread())
|
||||
{
|
||||
RenderSystem.recordRenderCall(this::clearBufferState);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (LodVertexFormatElement LodVertexFormatElement : this.getElements())
|
||||
{
|
||||
LodVertexFormatElement.clearBufferState();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* not currently needed has-Position/Normal/Color/UV
|
||||
public boolean hasPosition()
|
||||
{
|
||||
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.POSITION);
|
||||
}
|
||||
|
||||
public boolean hasNormal()
|
||||
{
|
||||
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.NORMAL);
|
||||
}
|
||||
|
||||
public boolean hasColor()
|
||||
{
|
||||
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.COLOR);
|
||||
}
|
||||
|
||||
public boolean hasUV(int which)
|
||||
{
|
||||
return elements.stream().anyMatch(e -> e.getUsage() == LodVertexFormatElement.Usage.UV && e.getIndex() == which);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
-168
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* 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.vertexFormat;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* This object is used to build LodVertexFormats.
|
||||
* <p>
|
||||
* A (almost) exact copy of Minecraft's
|
||||
* VertexFormatElement class. <br>
|
||||
* A number of things were removed from the original
|
||||
* object since we didn't need them, specifically "usage".
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-13-2021
|
||||
*/
|
||||
public class LodVertexFormatElement
|
||||
{
|
||||
private final LodVertexFormatElement.DataType dataType;
|
||||
/** James isn't sure what index is for */
|
||||
private final int index;
|
||||
private final int count;
|
||||
private final int byteSize;
|
||||
private final boolean isPadding;
|
||||
|
||||
public LodVertexFormatElement(int newIndex, LodVertexFormatElement.DataType newType, int newCount, boolean isPadding)
|
||||
{
|
||||
this.dataType = newType;
|
||||
this.index = newIndex;
|
||||
this.count = newCount;
|
||||
this.byteSize = newType.getSize() * this.count;
|
||||
this.isPadding = isPadding;
|
||||
}
|
||||
|
||||
public final boolean getIsPadding()
|
||||
{
|
||||
return isPadding;
|
||||
}
|
||||
|
||||
public final LodVertexFormatElement.DataType getType()
|
||||
{
|
||||
return this.dataType;
|
||||
}
|
||||
|
||||
public final int getIndex()
|
||||
{
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public final int getByteSize()
|
||||
{
|
||||
return this.byteSize;
|
||||
}
|
||||
|
||||
// added by Forge
|
||||
public int getElementCount()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum DataType
|
||||
{
|
||||
FLOAT(4, "Float", GL32.GL_FLOAT),
|
||||
UBYTE(1, "Unsigned Byte", GL32.GL_UNSIGNED_BYTE),
|
||||
BYTE(1, "Byte", GL32.GL_BYTE),
|
||||
USHORT(2, "Unsigned Short", GL32.GL_UNSIGNED_SHORT),
|
||||
SHORT(2, "Short", GL32.GL_SHORT),
|
||||
UINT(4, "Unsigned Int", GL32.GL_UNSIGNED_INT),
|
||||
INT(4, "Int", GL32.GL_INT);
|
||||
|
||||
private final int size;
|
||||
private final String name;
|
||||
private final int glType;
|
||||
|
||||
DataType(int sizeInBytes, String newName, int openGlDataType)
|
||||
{
|
||||
this.size = sizeInBytes;
|
||||
this.name = newName;
|
||||
this.glType = openGlDataType;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public int getGlType()
|
||||
{
|
||||
return this.glType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int i = this.dataType.hashCode();
|
||||
i = 31 * i + this.index;
|
||||
return 31 * i + this.count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.count + "," + this.dataType.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
LodVertexFormatElement LodVertexFormatElement = (LodVertexFormatElement) obj;
|
||||
if (this.count != LodVertexFormatElement.count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.index != LodVertexFormatElement.index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.dataType != LodVertexFormatElement.dataType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.vertexFormat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* A (almost) exact copy of MC's
|
||||
* DefaultVertexFormats class.
|
||||
*/
|
||||
public class VertexFormats
|
||||
{
|
||||
public static final LodVertexFormatElement ELEMENT_POSITION = new LodVertexFormatElement(3, LodVertexFormatElement.DataType.USHORT, 3, false);
|
||||
public static final LodVertexFormatElement ELEMENT_COLOR = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.UBYTE, 4, false);
|
||||
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_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());
|
||||
|
||||
}
|
||||
@@ -20,8 +20,6 @@
|
||||
package com.seibel.distanthorizons.core.util;
|
||||
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.vertexFormat.VertexFormats;
|
||||
import com.seibel.distanthorizons.core.render.vertexFormat.LodVertexFormat;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
@@ -108,9 +106,6 @@ 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 DH_VERTEX_FORMAT = VertexFormats.POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT_MATERIAL_ID_NORMAL_INDEX;
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.util;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
@@ -64,7 +65,7 @@ public class RenderUtil
|
||||
*
|
||||
* @param mcProjMat Minecraft's current projection matrix
|
||||
*/
|
||||
public static Mat4f createLodProjectionMatrix(Mat4f mcProjMat)
|
||||
public static Mat4f createLodProjectionMatrix(DhApiMat4f mcProjMat)
|
||||
{
|
||||
// in James' testing a near clip plane distance of 2 blocks is enough to allow the fragment
|
||||
// culling to take effect instead of seeing the near clip plane.
|
||||
@@ -81,18 +82,18 @@ public class RenderUtil
|
||||
float farClipDist = (float) RenderUtil.getFarClipPlaneDistanceInBlocks();
|
||||
|
||||
// Create a copy of the current matrix, so it won't be modified.
|
||||
Mat4f lodProj = mcProjMat.copy();
|
||||
Mat4f lodProj = new Mat4f(mcProjMat);
|
||||
// Set new far and near clip plane values.
|
||||
lodProj.setClipPlanes(nearClipDist, farClipDist);
|
||||
return lodProj;
|
||||
}
|
||||
|
||||
/** create and return a new projection matrix based on MC's modelView and projection matrices */
|
||||
public static Mat4f createLodModelViewMatrix(Mat4f mcModelViewMat)
|
||||
public static Mat4f createLodModelViewMatrix(DhApiMat4f mcModelViewMat)
|
||||
{
|
||||
// nothing beyond copying needs to be done to MC's MVM currently,
|
||||
// this method is just here in case that changes in the future
|
||||
return mcModelViewMat.copy();
|
||||
return new Mat4f(mcModelViewMat);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
+3
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
/**
|
||||
@@ -33,4 +34,6 @@ public interface IVersionConstants extends IBindable
|
||||
{
|
||||
String getMinecraftVersion();
|
||||
|
||||
EDhApiRenderApi getDefaultRenderingApi();
|
||||
|
||||
}
|
||||
|
||||
+13
-1
@@ -23,6 +23,10 @@ import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.IBatchGeneratorEnvironmentWrapper;
|
||||
@@ -30,7 +34,6 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* This handles creating abstract wrapper objects.
|
||||
@@ -102,4 +105,13 @@ public interface IWrapperFactory extends IDhApiWrapperFactory, IBindable
|
||||
*/
|
||||
IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException;
|
||||
|
||||
|
||||
|
||||
IVertexBufferWrapper createVboWrapper(String name);
|
||||
ILodContainerUniformBufferWrapper createLodContainerUniformWrapper();
|
||||
|
||||
IDhGenericObjectVertexBufferContainer createGenericObjectVboContainer();
|
||||
|
||||
IDhGenericRenderer createGenericRenderer();
|
||||
|
||||
}
|
||||
|
||||
-8
@@ -19,18 +19,10 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
public interface IMinecraftClientWrapper extends IBindable
|
||||
{
|
||||
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* 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 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 License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Used to sync GL state changes between DH and MC.
|
||||
* This is specifically important for other mods that change MC's rendering like Iris.
|
||||
*/
|
||||
public interface IMinecraftGLWrapper extends IBindable
|
||||
{
|
||||
|
||||
// scissor //
|
||||
|
||||
/** @see GL32#GL_SCISSOR_TEST */
|
||||
void enableScissorTest();
|
||||
/** @see GL32#GL_SCISSOR_TEST */
|
||||
void disableScissorTest();
|
||||
|
||||
|
||||
// stencil //
|
||||
|
||||
///** @see GL32#GL_SCISSOR_TEST */
|
||||
//void enableScissorTest() { GlStateManager._enableScissorTest(); }
|
||||
///** @see GL32#GL_SCISSOR_TEST */
|
||||
//void disableScissorTest() { GlStateManager._disableScissorTest(); }
|
||||
|
||||
|
||||
// depth //
|
||||
|
||||
/** @see GL32#GL_DEPTH_TEST */
|
||||
void enableDepthTest();
|
||||
/** @see GL32#GL_DEPTH_TEST */
|
||||
void disableDepthTest();
|
||||
|
||||
/** @see GL32#glDepthFunc(int) */
|
||||
void glDepthFunc(int func);
|
||||
|
||||
/** @see GL32#glDepthMask(boolean) */
|
||||
void enableDepthMask();
|
||||
/** @see GL32#glDepthMask(boolean) */
|
||||
void disableDepthMask();
|
||||
|
||||
|
||||
|
||||
// blending //
|
||||
|
||||
/** @see GL32#GL_BLEND */
|
||||
void enableBlend();
|
||||
/** @see GL32#GL_BLEND */
|
||||
void disableBlend();
|
||||
|
||||
/** @see GL32#glBlendFunc */
|
||||
void glBlendFunc(int sfactor, int dfactor);
|
||||
/** @see GL32#glBlendFuncSeparate */
|
||||
void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha);
|
||||
|
||||
|
||||
// frame buffers //
|
||||
|
||||
/** @see GL32#glBindFramebuffer */
|
||||
void glBindFramebuffer(int target, int framebuffer);
|
||||
|
||||
|
||||
// buffers //
|
||||
|
||||
/** @see GL32#glGenBuffers() */
|
||||
int glGenBuffers();
|
||||
|
||||
/** @see GL32#glDeleteBuffers(int) */
|
||||
void glDeleteBuffers(int buffer);
|
||||
|
||||
|
||||
|
||||
// culling //
|
||||
|
||||
/** @see GL32#GL_CULL_FACE */
|
||||
void enableFaceCulling();
|
||||
/** @see GL32#GL_CULL_FACE */
|
||||
void disableFaceCulling();
|
||||
|
||||
|
||||
// textures //
|
||||
|
||||
/** @see GL32#glGenTextures() */
|
||||
int glGenTextures();
|
||||
/** @see GL32#glDeleteTextures(int) */
|
||||
void glDeleteTextures(int texture);
|
||||
|
||||
/** @see GL32#glActiveTexture(int) */
|
||||
void glActiveTexture(int textureId);
|
||||
/**
|
||||
* Only works for textures bound via this system. <br>
|
||||
* Returns the bound {@link GL32#GL_TEXTURE_BINDING_2D}
|
||||
*/
|
||||
int getActiveTexture();
|
||||
|
||||
/**
|
||||
* Always binds to {@link GL32#GL_TEXTURE_2D}
|
||||
* @see GL32#glBindTexture(int, int)
|
||||
*/
|
||||
void glBindTexture(int texture);
|
||||
|
||||
}
|
||||
-9
@@ -20,7 +20,6 @@
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.misc;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
@@ -28,13 +27,5 @@ import org.lwjgl.opengl.GL32;
|
||||
*/
|
||||
public interface ILightMapWrapper extends IBindable
|
||||
{
|
||||
/**
|
||||
* which texture index IE 0,1,2... the lightmap will be bound to. <Br>
|
||||
* Related to but different from {@link GL32#GL_TEXTURE0}.
|
||||
*/
|
||||
int BOUND_INDEX = 0;
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
|
||||
}
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.render;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
public abstract class AbstractDhRenderApiDefinition implements IBindable
|
||||
{
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
/** Used for debugging */
|
||||
public abstract String getApiName();
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//============//
|
||||
// singletons //
|
||||
//============//
|
||||
//region
|
||||
|
||||
public abstract IDhMetaRenderer getMetaRenderer();
|
||||
public abstract IDhTerrainRenderer getTerrainRenderer();
|
||||
public abstract IDhSsaoRenderer getSsaoRenderer();
|
||||
public abstract IDhFogRenderer getFogRenderer();
|
||||
public abstract IDhFarFadeRenderer getFarFadeRenderer();
|
||||
public abstract AbstractDebugWireframeRenderer getDebugWireframeRenderer();
|
||||
public abstract IDhVanillaFadeRenderer getVanillaFadeRenderer();
|
||||
public abstract IDhTestTriangleRenderer getTestTriangleRenderer();
|
||||
|
||||
public void bindRenderers()
|
||||
{
|
||||
SingletonInjector.INSTANCE.bind(AbstractDhRenderApiDefinition.class, this);
|
||||
|
||||
SingletonInjector.INSTANCE.bind(IDhMetaRenderer.class, this.getMetaRenderer());
|
||||
SingletonInjector.INSTANCE.bind(IDhTerrainRenderer.class, this.getTerrainRenderer());
|
||||
SingletonInjector.INSTANCE.bind(IDhSsaoRenderer.class, this.getSsaoRenderer());
|
||||
SingletonInjector.INSTANCE.bind(IDhFogRenderer.class, this.getFogRenderer());
|
||||
SingletonInjector.INSTANCE.bind(IDhFarFadeRenderer.class, this.getFarFadeRenderer());
|
||||
SingletonInjector.INSTANCE.bind(AbstractDebugWireframeRenderer.class, this.getDebugWireframeRenderer());
|
||||
SingletonInjector.INSTANCE.bind(IDhVanillaFadeRenderer.class, this.getVanillaFadeRenderer());
|
||||
SingletonInjector.INSTANCE.bind(IDhTestTriangleRenderer.class, this.getTestTriangleRenderer());
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// factories //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
// these methods are used by WrapperFactory
|
||||
|
||||
/**
|
||||
* Generic renderers are created for each level they're used in
|
||||
* so we can't just define a single instance.
|
||||
*/
|
||||
public abstract IDhGenericRenderer createGenericRenderer();
|
||||
|
||||
public abstract IVertexBufferWrapper createVboWrapper(String name);
|
||||
public abstract ILodContainerUniformBufferWrapper createLodContainerUniformWrapper();
|
||||
public abstract IDhGenericObjectVertexBufferContainer createGenericVboContainer();
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.render.objects;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IDhGenericObjectVertexBufferContainer extends AutoCloseable
|
||||
{
|
||||
void uploadDataToGpu();
|
||||
|
||||
void updateVertexData(List<DhApiRenderableBox> uploadBoxList);
|
||||
|
||||
EState getState();
|
||||
void setState(EState state);
|
||||
|
||||
@Override
|
||||
void close();
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
enum EState
|
||||
{
|
||||
NEW,
|
||||
UPDATING_DATA,
|
||||
READY_TO_UPLOAD,
|
||||
RENDER,
|
||||
|
||||
ERROR,
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.wrapperInterfaces.render.objects;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||
|
||||
/**
|
||||
* @see LodBufferContainer
|
||||
*/
|
||||
public interface ILodContainerUniformBufferWrapper extends IUniformBufferWrapper
|
||||
{
|
||||
|
||||
void createUniformData(LodBufferContainer bufferContainer);
|
||||
|
||||
void tryUpload();
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.wrapperInterfaces.render.objects;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
public interface IUniformBufferWrapper extends IBindable, AutoCloseable
|
||||
{
|
||||
void upload();
|
||||
|
||||
@Override
|
||||
void close();
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.wrapperInterfaces.render.objects;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public interface IVertexBufferWrapper extends IBindable, AutoCloseable
|
||||
{
|
||||
void upload(ByteBuffer buffer, int vertexCount);
|
||||
|
||||
@Override
|
||||
void close();
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.wrapperInterfaces.render.renderPass;
|
||||
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
public interface IDhFarFadeRenderer extends IBindable
|
||||
{
|
||||
|
||||
void render(RenderParams renderParams);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user