Add the option to use either Blaze3D or OpenGL rendering APIs

This commit is contained in:
James Seibel
2026-03-10 11:47:40 -05:00
parent 294013eff0
commit 3555133d7f
35 changed files with 965 additions and 1502 deletions
+13 -18
View File
@@ -268,11 +268,6 @@ subprojects { p ->
// Netty
implementation("io.netty:netty-buffer:${rootProject.netty_version}")
// Remember, for lwjgl dependencies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing
forgeShadowMe("org.lwjgl:lwjgl-jawt:${rootProject.lwjgl_version}") {
exclude group: "org.lwjgl", module: "lwjgl" // This module is imported by Minecraft so exclude it
}
//==========================//
@@ -320,11 +315,7 @@ subprojects { p ->
relocate "com.seibel.distanthorizons.common", "loaderCommon.${p.name}.com.seibel.distanthorizons.common" // Move the loader files to a different location
}
def librariesLocation = "DistantHorizons.libraries"
// LWJGL
// Only ever shadow the dependencies we use otherwise some stuff would break when running on an external client
relocate "org.lwjgl.system.jawt", "${librariesLocation}.lwjgl.system.jawt"
// Compression (LZ4)
relocate "net.jpountz", "${librariesLocation}.jpountz"
@@ -629,26 +620,30 @@ allprojects { p ->
if (p == project(":core")) {
OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem;
// Set the OS lwjgl is using to the current os
// Set the OS lwjgl is using to the current os
project.ext.lwjglNatives = "natives-" + os.toFamilyName()
dependencies { // All of these dependencies are in Vanilla Minecraft, but we need to depend on it as we arent importing Minecraft in the core
// Imports most of lwjgl's libraries (well, only the ones that we need)
dependencies {
// All of these dependencies are in Vanilla Minecraft, but we need to depend on them as we arent importing Minecraft in the core
// Imports most of lwjgl's libraries
implementation platform("org.lwjgl:lwjgl-bom:${rootProject.lwjgl_version}")
// REMEMBER: Dont shadow stuff here, these are just the libs that are included in Minecraft so that the core can use
// REMEMBER: Don't shadow stuff here, these are just the libs that are included in Minecraft so that the core can use them
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"
implementation "org.joml:joml:${rootProject.joml_version}"
@@ -52,9 +52,9 @@ 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.RenderParams;
import com.seibel.distanthorizons.common.render.nativeGl.generic.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
import com.seibel.distanthorizons.common.render.nativeGl.generic.RenderableBoxGroup;
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d;
@@ -17,6 +17,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*;
public class BlazeDhRenderApiDefinition extends AbstractDhRenderApiDefinition
{
public String getApiName() { return "Blaze3D"; }
@Override public IDhTerrainRenderer getTerrainRenderer() { return BlazeDhTerrainRenderer.INSTANCE; }
@Override public IDhSsaoRenderer getSsaoRenderer() { return BlazeDhSsaoRenderer.INSTANCE; }
@@ -65,7 +65,6 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
private BlazeDhApplyRenderer applyRenderer;
private VertexFormat vertexFormat;
private RenderPipeline opaquePipeline;
private RenderPipeline transparentPipeline;
private boolean init = false;
@@ -85,18 +84,7 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
//=============//
//region
private BlazeDhTerrainRenderer()
{
this.vertexFormat = VertexFormat.builder()
.add("vPosition", DhBlazeVertexFormatUtil.SHORT_XYZ_POS)
.add("meta", DhBlazeVertexFormatUtil.META)
.add("vColor", DhBlazeVertexFormatUtil.RGBA_UBYTE_COLOR)
.add("irisMaterial", DhBlazeVertexFormatUtil.IRIS_MATERIAL)
.add("irisNormal", DhBlazeVertexFormatUtil.IRIS_NORMAL)
.add("paddingTwo", DhBlazeVertexFormatUtil.BYTE_PAD)
.add("paddingThree", DhBlazeVertexFormatUtil.BYTE_PAD) // padding is to make sure the format is a multiple of 4
.build();
}
private BlazeDhTerrainRenderer() { }
private void tryInit()
{
@@ -113,6 +101,15 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
"apply/blaze/vert", "apply/blaze/frag"
);
VertexFormat vertexFormat = VertexFormat.builder()
.add("vPosition", DhBlazeVertexFormatUtil.SHORT_XYZ_POS)
.add("meta", DhBlazeVertexFormatUtil.META)
.add("vColor", DhBlazeVertexFormatUtil.RGBA_UBYTE_COLOR)
.add("irisMaterial", DhBlazeVertexFormatUtil.IRIS_MATERIAL)
.add("irisNormal", DhBlazeVertexFormatUtil.IRIS_NORMAL)
.add("paddingTwo", DhBlazeVertexFormatUtil.BYTE_PAD)
.add("paddingThree", DhBlazeVertexFormatUtil.BYTE_PAD) // padding is to make sure the format is a multiple of 4
.build();
RenderPipeline.Builder pipelineBuilder = RenderPipeline.builder();
{
@@ -132,7 +129,7 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
pipelineBuilder.withUniform("vertSharedUniformBlock", UniformType.UNIFORM_BUFFER);
pipelineBuilder.withUniform("fragUniformBlock", UniformType.UNIFORM_BUFFER);
pipelineBuilder.withVertexFormat(this.vertexFormat, VertexFormat.Mode.TRIANGLES);
pipelineBuilder.withVertexFormat(vertexFormat, VertexFormat.Mode.TRIANGLES);
}
// opaque
@@ -150,9 +147,6 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
//endregion
@Override
public int getVertexByteSize() { return this.vertexFormat.getVertexSize(); }
//========//
@@ -398,6 +392,12 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
private String getIndexBufferName() { return "distantHorizons:LodIndexBuffer"; }
private String getRenderPassName() { return "distantHorizons:McLodRenderer"; }
@Override
public void runRenderPassSetup(RenderParams renderParams) {}
@Override
public void runRenderPassCleanup(RenderParams renderParams) {}
@Override
public void applyToMcTexture()
{
@@ -11,7 +11,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLEnums;
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
import com.seibel.distanthorizons.common.render.nativeGl.generic.RenderableBoxGroup;
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
import com.seibel.distanthorizons.core.util.ColorUtil;
import org.lwjgl.opengl.GL32;
@@ -19,30 +19,58 @@
package com.seibel.distanthorizons.common.render.nativeGl;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
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.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.QuadElementBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.texture.*;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.AbstractVertexAttribute;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.VertexAttributePostGL43;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.VertexAttributePreGL43;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.VertexPointer;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.apply.DhApplyShader;
import com.seibel.distanthorizons.common.render.nativeGl.util.vertexFormat.LodVertexFormat;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
import com.seibel.distanthorizons.core.util.LodUtil;
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.RenderBufferHandler;
import com.seibel.distanthorizons.core.render.RenderParams;
import com.seibel.distanthorizons.core.util.RenderUtil;
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.misc.ILightMapWrapper;
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTerrainRenderer;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL32;
/**
* Handles rendering the normal LOD terrain.
* @see LodQuadBuilder
*/
public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShaderProgram
public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShaderProgram, IDhTerrainRenderer
{
public final AbstractVertexAttribute vao;
@@ -73,6 +101,7 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
//=============//
// constructor //
//=============//
//region
// This will bind AbstractVertexAttribute
public DhTerrainShaderProgram()
@@ -136,11 +165,14 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
}
//endregion
//=========//
// methods //
//=========//
//region
@Override
public void bind()
@@ -224,4 +256,537 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
@Override
public boolean overrideThisFrame() { return true; }
//endregion
@Override
public void runRenderPassSetup(RenderParams renderParams) { OpenGlRenderState.INSTANCE.runRenderPassSetup(renderParams); }
@Override
public void runRenderPassCleanup(RenderParams renderParams) { OpenGlRenderState.INSTANCE.runRenderPassCleanup(renderParams); }
@Override
public void render(RenderParams renderEventParam, boolean opaquePass, SortedArraySet<LodBufferContainer> bufferContainers, IProfilerWrapper profiler)
{
OpenGlRenderState.INSTANCE.renderLodTerrain(bufferContainers, renderEventParam, opaquePass);
}
@Override
public void applyToMcTexture()
{
}
@Override
public void clearDepth()
{
}
@Override
public void clearColor()
{
}
public static class OpenGlRenderState
{
public static final DhLogger LOGGER = new DhLoggerBuilder()
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
.build();
public static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
.maxCountPerSecond(4)
.build();
public static final OpenGlRenderState INSTANCE = new OpenGlRenderState();
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
// 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 OpenGlRenderState#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 IDhApiShaderProgram lodShaderProgramThisFrame;
//
//
//
public void runRenderPassSetup(RenderParams renderParams)
{
boolean firstPass =
(renderParams.renderPass == EDhApiRenderPass.OPAQUE
|| renderParams.renderPass == EDhApiRenderPass.OPAQUE_AND_TRANSPARENT);
if (!this.renderObjectsCreated)
{
boolean setupSuccess = this.createRenderObjects();
if (!setupSuccess)
{
// shouldn't normally happen, but just in case
return;
}
this.renderObjectsCreated = true;
}
this.setGLState(renderParams, firstPass);
this.quadIBO.bind();
renderParams.lightmap.bind();
this.lodShaderProgramThisFrame = this.lodRenderProgram;
IDhApiShaderProgram lodShaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
if (lodShaderProgramOverride != null && this.lodShaderProgramThisFrame.overrideThisFrame())
{
this.lodShaderProgramThisFrame = lodShaderProgramOverride;
}
}
public void runRenderPassCleanup(RenderParams renderParams)
{
boolean runningDeferredPass = (renderParams.renderPass == EDhApiRenderPass.TRANSPARENT);
if (!runningDeferredPass)
{
//===================//
// 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);
}
//=============================//
// Apply to the MC Framebuffer //
//=============================//
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);
}
}
renderParams.lightmap.unbind();
this.quadIBO.unbind();
this.lodShaderProgramThisFrame.unbind();
}
//=================//
// 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(LodQuadBuilder.getMaxBufferByteSize());
// 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
public void renderLodTerrain(SortedArraySet<LodBufferContainer> bufferContainers, RenderParams renderEventParam, boolean opaquePass)
{
IDhApiShaderProgram shaderProgram = this.lodShaderProgramThisFrame;
//=======================//
// 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)
{
// 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();
}
if (bufferContainers != null)
{
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
{
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
this.setShaderProgramMvmOffset(bufferContainer.minCornerBlockPos, shaderProgram, renderEventParam);
IVertexBufferWrapper[] vertexBuffers = (opaquePass ? bufferContainer.vbos : bufferContainer.vbosTransparent);
for (int vboIndex = 0; vboIndex < vertexBuffers.length; vboIndex++)
{
GLVertexBuffer vbo = (GLVertexBuffer) vertexBuffers[vboIndex];
if (vbo == null)
{
continue;
}
if (vbo.getVertexCount() == 0)
{
continue;
}
vbo.bind();
shaderProgram.bindVertexBuffer(vbo.getId());
GL32.glDrawElements(
GL32.GL_TRIANGLES,
(int)(vbo.getVertexCount() * 1.5),
this.quadIBO.getType(), 0);
vbo.unbind();
}
}
}
//=========================//
// 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
}
}
@@ -1,766 +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.common.render.nativeGl;
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.common.render.nativeGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.QuadElementBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.texture.*;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.apply.DhApplyShader;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade.DhFadeRenderer;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
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.common.render.nativeGl.postProcessing.fog.FogRenderer;
import com.seibel.distanthorizons.core.render.RenderParams;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ssao.SSAORenderer;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
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.IDhGenericRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTestTriangleRenderer;
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>
* This is where LODs are draw to the world.
*/
public class LodRenderer
{
public static final DhLogger LOGGER = new DhLoggerBuilder()
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
.build();
public static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
.maxCountPerSecond(4)
.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 MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
public static final LodRenderer INSTANCE = new LodRenderer();
// 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;
//=============//
// constructor //
//=============//
private LodRenderer() { }
//===========//
// rendering //
//===========//
//region
/**
* This will draw both opaque and transparent LODs if
* {@link DhApiRenderProxy#getDeferTransparentRendering()} is false,
* otherwise it will only render opaque LODs.
*/
public void render(RenderParams renderParams, IProfilerWrapper profiler)
{ this.renderLodPass(renderParams, profiler, false); }
/**
* This method is designed for Iris to be able
* to draw water in a deferred rendering context.
* It needs to be updated with any major changes,
* but shouldn't be activated as per deferWaterRendering.
*/
public void renderDeferred(RenderParams renderParams, IProfilerWrapper profiler)
{ this.renderLodPass(renderParams, profiler, true); }
private void renderLodPass(RenderParams renderParams, IProfilerWrapper profiler, boolean runningDeferredPass)
{
//====================//
// validate rendering //
//====================//
boolean deferTransparentRendering = DhApiRenderProxy.INSTANCE.getDeferTransparentRendering();
if (runningDeferredPass
&& !deferTransparentRendering)
{
return;
}
boolean firstPass = !runningDeferredPass;
// RenderParams parameter validation should be done before this
if (!renderParams.validationRun)
{
throw new IllegalArgumentException("Render parameters validation");
}
RenderBufferHandler renderBufferHandler = renderParams.renderBufferHandler;
IDhGenericRenderer genericRenderer = renderParams.genericRenderer;
ILightMapWrapper lightmap = renderParams.lightmap;
//=================//
// rendering setup //
//=================//
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderSetupEvent.class, renderParams);
profiler.push("LOD GL setup");
if (!this.renderObjectsCreated)
{
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())
{
LOGGER.info("Overriding vanilla MC settings to better fit Distant Horizons... This behavior can be disabled in the Distant Horizons config.");
MC.disableVanillaClouds();
MC.disableVanillaChunkFadeIn();
MC.disableFabulousTransparency();
}
this.renderObjectsCreated = true;
}
this.setGLState(renderParams, firstPass);
lightmap.bind();
this.quadIBO.bind();
if (firstPass)
{
// we only need to sort/cull the LODs during the first 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;
}
//===========//
// rendering //
//===========//
if (!runningDeferredPass)
{
//=========================//
// opaque and non-deferred //
// transparent rendering //
//=========================//
// opaque LODs
profiler.popPush("LOD Opaque");
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ true);
// custom objects with SSAO
if (Config.Client.Advanced.Graphics.GenericRendering.enableGenericRendering.get())
{
profiler.popPush("Custom Objects");
genericRenderer.render(renderParams, profiler, true);
}
// SSAO
if (Config.Client.Advanced.Graphics.Ssao.enableSsao.get())
{
profiler.popPush("LOD SSAO");
SSAORenderer.INSTANCE.render(new Mat4f(renderParams.dhProjectionMatrix), renderParams.partialTicks);
}
// custom objects without SSAO
if (Config.Client.Advanced.Graphics.GenericRendering.enableGenericRendering.get())
{
profiler.popPush("Custom Objects");
genericRenderer.render(renderParams, profiler, false);
}
// combined pass transparent rendering
if (!deferTransparentRendering
&& Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
{
profiler.popPush("LOD Transparent");
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ false);
}
// 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()))
{
profiler.popPush("Fade Far Clip Fade");
DhFadeRenderer.INSTANCE.render(
new Mat4f(renderParams.mcModelViewMatrix), new Mat4f(renderParams.mcProjectionMatrix),
renderParams.partialTicks, profiler);
}
// fog
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);
}
//=================//
// debug rendering //
//=================//
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); // TODO
}
//===================//
// 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);
}
//=============================//
// Apply to the MC Framebuffer //
//=============================//
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);
}
}
else
{
//====================//
// deferred rendering //
//====================//
if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
{
profiler.popPush("LOD Transparent");
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ false);
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);
}
}
}
//================//
// render cleanup //
//================//
profiler.popPush("LOD cleanup");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderCleanupEvent.class, renderParams);
lightmap.unbind();
this.quadIBO.unbind();
lodShaderProgram.unbind();
// end of internal LOD profiling
profiler.pop();
}
//endregion
//=================//
// 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(LodQuadBuilder.getMaxBufferByteSize());
// 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)
{
//=======================//
// 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)
{
// 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();
}
//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
IDhTestTriangleRenderer testRenderer = SingletonInjector.INSTANCE.get(IDhTestTriangleRenderer.class);
testRenderer.render();
//TestRenderer.INSTANCE.render();
//McTestRenderer.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
}
@@ -25,15 +25,11 @@ import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderP
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.AbstractVertexAttribute;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.VertexPointer;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
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.RenderParams;
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
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 org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
@@ -43,9 +39,9 @@ import java.nio.ByteOrder;
* Handles rendering the wireframe particles
* that are used for seeing what the system's doing.
*/
public class DebugRenderer extends AbstractDebugWireframeRenderer
public class OpenGlDebugWireframeRenderer extends AbstractDebugWireframeRenderer
{
public static DebugRenderer INSTANCE = new DebugRenderer();
public static OpenGlDebugWireframeRenderer INSTANCE = new OpenGlDebugWireframeRenderer();
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
@@ -102,7 +98,7 @@ public class DebugRenderer extends AbstractDebugWireframeRenderer
//=============//
//region
private DebugRenderer() { }
private OpenGlDebugWireframeRenderer() { }
public void init()
{
@@ -1,5 +1,14 @@
package com.seibel.distanthorizons.common.render.nativeGl;
import com.seibel.distanthorizons.common.render.nativeGl.generic.OpenGlGenericObjectRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.generic.OpenGlGenericObjectVertexContainer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.OpenGlDummyUniformData;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade.DhFarFadeRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade.VanillaFadeRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fog.DhFogRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ssao.DhSSAORenderer;
import com.seibel.distanthorizons.common.render.nativeGl.test.GlTestTriangleRenderer;
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
@@ -10,21 +19,23 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*;
public class OpenGlDhRenderApiDefinition extends AbstractDhRenderApiDefinition
{
@Override public IDhTerrainRenderer getTerrainRenderer() { return null; }
@Override public IDhSsaoRenderer getSsaoRenderer() { return null; }
@Override public IDhFogRenderer getFogRenderer() { return null; }
@Override public IDhFarFadeRenderer getFarFadeRenderer() { return null; }
@Override public AbstractDebugWireframeRenderer getDebugWireframeRenderer() { return null; }
public String getApiName() { return "OpenGL"; }
@Override public IDhVanillaFadeRenderer getVanillaFadeRenderer() { return null; }
@Override public IDhTestTriangleRenderer getTestTriangleRenderer() { return null; }
@Override public IDhTerrainRenderer getTerrainRenderer() { return new DhTerrainShaderProgram(); } // TODO not implemented // TODO how to support Iris?
@Override public IDhSsaoRenderer getSsaoRenderer() { return DhSSAORenderer.INSTANCE; }
@Override public IDhFogRenderer getFogRenderer() { return DhFogRenderer.INSTANCE; }
@Override public IDhFarFadeRenderer getFarFadeRenderer() { return DhFarFadeRenderer.INSTANCE; }
@Override public AbstractDebugWireframeRenderer getDebugWireframeRenderer() { return OpenGlDebugWireframeRenderer.INSTANCE; }
@Override public IDhGenericRenderer createGenericRenderer() { return null; }
@Override public IDhVanillaFadeRenderer getVanillaFadeRenderer() { return VanillaFadeRenderer.INSTANCE; }
@Override public IDhTestTriangleRenderer getTestTriangleRenderer() { return GlTestTriangleRenderer.INSTANCE; }
@Override public IDhGenericRenderer createGenericRenderer() { return OpenGlGenericObjectRenderer.INSTANCE; }
@Override public IVertexBufferWrapper createVboWrapper(String name) { return null; }
@Override public ILodContainerUniformBufferWrapper createLodContainerUniformWrapper() { return null; }
@Override public IDhGenericObjectVertexBufferContainer createGenericVboContainer() { return null; }
@Override public IVertexBufferWrapper createVboWrapper(String name) { return new GLVertexBuffer(); }
@Override public ILodContainerUniformBufferWrapper createLodContainerUniformWrapper() { return new OpenGlDummyUniformData(); }
@Override public IDhGenericObjectVertexBufferContainer createGenericVboContainer() { return new OpenGlGenericObjectVertexContainer(); }
@@ -1,75 +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.common.render.nativeGl.generic;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.DhLogger;
import java.util.List;
import java.util.*;
/**
* Handles creating {@link DhApiRenderableBox}.
*
* @see IDhApiCustomRenderRegister
* @see DhApiRenderableBox
*/
public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFactory
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
public static final GenericRenderObjectFactory INSTANCE = new GenericRenderObjectFactory();
//=============//
// constructor //
//=============//
private GenericRenderObjectFactory() { }
//================//
// group creation //
//================//
@Override
public IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox box)
{
ArrayList<DhApiRenderableBox> list = new ArrayList<>();
list.add(box);
return this.createAbsolutePositionedGroup(resourceLocation, list);
}
@Override
public IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList)
{ return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); }
@Override
public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List<DhApiRenderableBox> boxList)
{ return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(0, 0, 0), boxList, false); }
}
@@ -31,20 +31,21 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.GLElementBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
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.RenderParams;
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
import com.seibel.distanthorizons.core.util.LodUtil;
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.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
@@ -74,6 +75,9 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
private static final DhApiRenderableBoxGroupShading DEFAULT_SHADING = DhApiRenderableBoxGroupShading.getUnshaded();
public static final OpenGlGenericObjectRenderer INSTANCE = new OpenGlGenericObjectRenderer();
/**
* Can be used to troubleshoot the renderer.
* If enabled several debug objects will render around (0,150,0).
@@ -86,7 +90,7 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
private IDhApiGenericObjectShaderProgram instancedShaderProgram;
private IDhApiGenericObjectShaderProgram directShaderProgram;
//private GLVertexBuffer boxVertexBuffer;
private GLVertexBuffer boxVertexBuffer;
private GLElementBuffer boxIndexBuffer;
private boolean instancedRenderingAvailable;
@@ -172,7 +176,7 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
//=============//
//region
public OpenGlGenericObjectRenderer() { }
private OpenGlGenericObjectRenderer() { }
public void init()
{
@@ -219,9 +223,9 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
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);
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
@@ -425,7 +429,7 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
}
shaderProgram.bind(renderEventParam);
//shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
this.boxIndexBuffer.bind();
@@ -474,7 +478,7 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
boxGroup.tryUpdateInstancedDataAsync();
// skip groups that haven't been uploaded yet
if (boxGroup.vertexBufferContainer.getState() != NativeGlGenericObjectVertexContainer.EState.RENDER)
if (boxGroup.vertexBufferContainer.getState() != OpenGlGenericObjectVertexContainer.EState.RENDER)
{
continue;
}
@@ -556,7 +560,7 @@ public class OpenGlGenericObjectRenderer implements IDhGenericRenderer
// Bind instance data //
profiler.popPush("binding");
NativeGlGenericObjectVertexContainer container = (NativeGlGenericObjectVertexContainer)(boxGroup.vertexBufferContainer);
OpenGlGenericObjectVertexContainer container = (OpenGlGenericObjectVertexContainer)(boxGroup.vertexBufferContainer);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.color);
GL32.glEnableVertexAttribArray(1);
@@ -4,6 +4,7 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
import org.lwjgl.opengl.GL32;
@@ -16,7 +17,7 @@ import java.util.List;
*
* @see RenderableBoxGroup
*/
public class NativeGlGenericObjectVertexContainer implements IDhGenericObjectVertexBufferContainer
public class OpenGlGenericObjectVertexContainer implements IDhGenericObjectVertexBufferContainer
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
@@ -51,19 +52,6 @@ public class NativeGlGenericObjectVertexContainer implements IDhGenericObjectVer
//===========================//
//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();
@@ -118,11 +106,13 @@ public class NativeGlGenericObjectVertexContainer implements IDhGenericObjectVer
this.materialData[i] = box.material;
}
this.state = NativeGlGenericObjectVertexContainer.EState.READY_TO_UPLOAD;
this.state = OpenGlGenericObjectVertexContainer.EState.READY_TO_UPLOAD;
}
public void uploadDataToGpu()
{
this.tryCreateBuffers();
// Upload transformation matrices
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.chunkPos);
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.chunkPosData, GL32.GL_DYNAMIC_DRAW);
@@ -141,6 +131,18 @@ public class NativeGlGenericObjectVertexContainer implements IDhGenericObjectVer
this.state = EState.RENDER;
}
/** needs to be done on the render thread */
private void tryCreateBuffers()
{
if (this.chunkPos == 0)
{
this.chunkPos = GLMC.glGenBuffers();
this.subChunkPos = GLMC.glGenBuffers();
this.scale = GLMC.glGenBuffers();
this.color = GLMC.glGenBuffers();
this.material = GLMC.glGenBuffers();
}
}
//endregion
@@ -1,361 +0,0 @@
package com.seibel.distanthorizons.common.render.nativeGl.generic;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
import org.jetbrains.annotations.Nullable;
import java.io.Closeable;
import java.util.*;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class RenderableBoxGroup
extends AbstractList<DhApiRenderableBox>
implements IDhApiRenderableBoxGroup, Closeable
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IWrapperFactory WRAPPER_FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
public static final AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0);
public final long id;
public final String resourceLocationNamespace;
public final String resourceLocationPath;
/** If false the boxes will be positioned relative to the level's origin */
public final boolean positionBoxesRelativeToGroupOrigin;
private final List<DhApiRenderableBox> boxList;
/** backup list which allows for uploading the boxes even it the main list is being modified on a different thread. */
private final List<DhApiRenderableBox> uploadBoxList;
private final DhApiVec3d originBlockPos;
public boolean active = true;
public boolean ssaoEnabled = true;
private boolean vertexDataDirty = true;
public byte skyLight = LodUtil.MAX_MC_LIGHT;
public byte blockLight = LodUtil.MIN_MC_LIGHT;
public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded();
@Nullable
public Consumer<DhApiRenderParam> beforeRenderFunc;
public Consumer<DhApiRenderParam> afterRenderFunc;
// instance data
public IDhGenericObjectVertexBufferContainer vertexBufferContainer = WRAPPER_FACTORY.createGenericObjectVboContainer();
/** double buffering for thread safety and to prevent locking the render thread during update */
private IDhGenericObjectVertexBufferContainer altVertexBufferContainer = WRAPPER_FACTORY.createGenericObjectVboContainer();
//=================//
// getters/setters //
//=================//
//region
@Override
public long getId() { return this.id; }
@Override
public String getResourceLocationNamespace() { return this.resourceLocationNamespace; }
@Override
public String getResourceLocationPath() { return this.resourceLocationPath; }
@Override
public void setOriginBlockPos(DhApiVec3d pos)
{
this.originBlockPos.x = pos.x;
this.originBlockPos.y = pos.y;
this.originBlockPos.z = pos.z;
}
@Override
public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); }
@Override
public void setSkyLight(int skyLight)
{
if (skyLight < LodUtil.MIN_MC_LIGHT
|| skyLight > LodUtil.MAX_MC_LIGHT)
{
throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
}
this.skyLight = (byte)skyLight;
}
@Override
public int getSkyLight() { return this.skyLight; }
@Override
public void setBlockLight(int blockLight)
{
if (blockLight < LodUtil.MIN_MC_LIGHT
|| blockLight > LodUtil.MAX_MC_LIGHT)
{
throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
}
this.blockLight = (byte)blockLight;
}
@Override
public int getBlockLight() { return this.blockLight; }
@Override
public void setPreRenderFunc(Consumer<DhApiRenderParam> func) { this.beforeRenderFunc = func; }
@Override
public void setPostRenderFunc(Consumer<DhApiRenderParam> func) { this.afterRenderFunc = func; }
@Override
public void setActive(boolean active) { this.active = active; }
@Override
public boolean isActive() { return this.active; }
@Override
public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; }
@Override
public boolean isSsaoEnabled() { return this.ssaoEnabled; }
@Override
public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; }
@Override
public DhApiRenderableBoxGroupShading getShading() { return this.shading; }
//endregion
//=============//
// constructor //
//=============//
//region
public RenderableBoxGroup(
String resourceLocation,
DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList,
boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException
{
String[] splitResourceLocation = resourceLocation.split(":");
if (splitResourceLocation.length != 2)
{
throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons.");
}
this.resourceLocationNamespace = splitResourceLocation[0];
this.resourceLocationPath = splitResourceLocation[1];
this.id = NEXT_ID_ATOMIC_INT.getAndIncrement();
this.boxList = Collections.synchronizedList(new ArrayList<>(boxList));
this.uploadBoxList = Collections.synchronizedList(new ArrayList<>(boxList));
this.originBlockPos = originBlockPos;
this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin;
}
//endregion
//=================//
// render building //
//=================//
//region
@Override
public void triggerBoxChange() { this.vertexDataDirty = true; }
/**
* Does nothing if the vertex data is already up-to-date
* and is meaningless if using direct rendering.
*/
public void tryUpdateInstancedDataAsync()
{
// if the alt container is done, swap it in
if (this.altVertexBufferContainer.getState() == NativeGlGenericObjectVertexContainer.EState.READY_TO_UPLOAD)
{
this.altVertexBufferContainer.uploadDataToGpu();
// swap VBO references for rendering
IDhGenericObjectVertexBufferContainer temp = this.vertexBufferContainer;
this.vertexBufferContainer = this.altVertexBufferContainer;
this.altVertexBufferContainer = temp;
this.vertexDataDirty = false;
return;
}
// if the vertex data is already up to date, do nothing
if (!this.vertexDataDirty)
{
return;
}
PriorityTaskPicker.Executor executor = ThreadPoolUtil.getRenderLoadingExecutor();
if (executor == null || executor.isTerminated())
{
return;
}
// if the alternate container is already updating, don't double-queue it
if (this.altVertexBufferContainer.getState() == NativeGlGenericObjectVertexContainer.EState.UPDATING_DATA)
{
return;
}
this.altVertexBufferContainer.setState(NativeGlGenericObjectVertexContainer.EState.UPDATING_DATA);
//this.altInstancedVbos.tryRunRenderThreadSetup();
// copy over the box list so we can upload without concurrent modification issues
this.uploadBoxList.clear();
synchronized (this.uploadBoxList)
{
this.uploadBoxList.addAll(this.boxList);
}
try
{
executor.runTask(() ->
{
try
{
this.altVertexBufferContainer.updateVertexData(this.uploadBoxList);
}
catch (Exception e)
{
LOGGER.error("Unexpected error updating instanced VBO data for: ["+this+"], error: ["+e.getMessage()+"].", e);
this.altVertexBufferContainer.setState(NativeGlGenericObjectVertexContainer.EState.ERROR);
}
});
}
catch (RejectedExecutionException ignore)
{
// the executor was shut down, it should be back up shortly and able to accept new jobs
this.altVertexBufferContainer.setState(NativeGlGenericObjectVertexContainer.EState.NEW);
}
}
//endregion
//===============//
// render events //
//===============//
//region
/**
* This is called before every frame, even if {@link this#isActive()} returns false. <br>
* {@link this#isActive()} can be changed at this point before the object is rendered to the frame.
*/
public void preRender(DhApiRenderParam renderEventParam)
{
if (this.beforeRenderFunc != null)
{
this.beforeRenderFunc.accept(renderEventParam);
}
}
/**
* Called after rendering is completed. <br>
* Can be used to handle any necessary cleanup.
*/
public void postRender(DhApiRenderParam renderEventParam)
{
if (this.afterRenderFunc != null)
{
this.afterRenderFunc.accept(renderEventParam);
}
}
//endregion
//================//
// List Overrides //
//================//
//region
@Override
public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); }
@Override
public DhApiRenderableBox get(int index) { return this.boxList.get(index); }
@Override
public int size() { return this.boxList.size(); }
@Override
public boolean removeIf(Predicate<? super DhApiRenderableBox> filter) { return this.boxList.removeIf(filter); }
@Override
public boolean remove(Object obj) { return this.boxList.remove(obj); }
@Override
public DhApiRenderableBox remove(int index) { return this.boxList.remove(index); }
@Override
public void replaceAll(UnaryOperator<DhApiRenderableBox> operator) { this.boxList.replaceAll(operator); }
@Override
public void sort(Comparator<? super DhApiRenderableBox> comparator) { this.boxList.sort(comparator); }
@Override
public void forEach(Consumer<? super DhApiRenderableBox> action) { this.boxList.forEach(action); }
@Override
public Spliterator<DhApiRenderableBox> spliterator() { return this.boxList.spliterator(); }
@Override
public Stream<DhApiRenderableBox> stream() { return this.boxList.stream(); }
@Override
public Stream<DhApiRenderableBox> parallelStream() { return this.boxList.parallelStream(); }
@Override
public void clear() { this.boxList.clear(); }
//endregion
//================//
// base overrides //
//================//
//region
@Override
public String toString() { return "["+this.resourceLocationNamespace+":"+this.resourceLocationPath+"] ID:["+this.id+"], pos:[("+this.originBlockPos.x+", "+this.originBlockPos.y+", "+this.originBlockPos.z+")], size:["+this.size()+"], active:["+this.active+"]"; }
@Override
public void close()
{
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread(() ->
{
this.vertexBufferContainer.close();
this.altVertexBufferContainer.close();
});
}
//endregion
}
@@ -0,0 +1,13 @@
package com.seibel.distanthorizons.common.render.nativeGl.glObject;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
public class OpenGlDummyUniformData implements ILodContainerUniformBufferWrapper
{
@Override public void createUniformData(LodBufferContainer bufferContainer) { }
@Override public void tryUpload() { }
@Override public void upload() { }
@Override public void close() { }
}
@@ -75,16 +75,20 @@ public class GLBuffer implements AutoCloseable
//==============//
// constructors //
//==============//
//region
static { CLEANUP_THREAD.execute(() -> runPhantomReferenceCleanupLoop()); }
public GLBuffer(boolean isBufferStorage) { this.create(isBufferStorage); }
//endregion
//=========//
// methods //
//=========//
//region
// Should be override by subclasses
public int getBufferBindingTarget() { return GL32.GL_COPY_READ_BUFFER; }
@@ -92,11 +96,14 @@ public class GLBuffer implements AutoCloseable
public void bind() { GL32.glBindBuffer(this.getBufferBindingTarget(), this.id); }
public void unbind() { GL32.glBindBuffer(this.getBufferBindingTarget(), 0); }
//endregion
//====================//
// create and destroy //
//====================//
//region
protected void create(boolean asBufferStorage)
{
@@ -168,11 +175,14 @@ public class GLBuffer implements AutoCloseable
});
}
//endregion
//==================//
// buffer uploading //
//==================//
//region
/**
* Assumes the GL Context is already bound. <br>
@@ -252,11 +262,14 @@ public class GLBuffer implements AutoCloseable
GL32.glBufferSubData(this.getBufferBindingTarget(), 0, bb);
}
//endregion
//===========//
// overrides //
//===========//
//================//
// base overrides //
//================//
//region
@Override
public void close() { this.destroyAsync(); }
@@ -268,11 +281,14 @@ public class GLBuffer implements AutoCloseable
"[id:" + this.id + ",size:" + this.size + (this.isMapped ? ",MAPPED" : "") + "]";
}
//endregion
//================//
// helper methods //
//================//
//region
/**
* Makes sure the buffer exists and is of the correct format
@@ -302,11 +318,14 @@ public class GLBuffer implements AutoCloseable
}
}
//endregion
//================//
// static cleanup //
//================//
//region
private static void runPhantomReferenceCleanupLoop()
{
@@ -342,4 +361,8 @@ public class GLBuffer implements AutoCloseable
}
}
//endregion
}
@@ -21,6 +21,9 @@ package com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer;
import java.nio.ByteBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLProxy;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
import org.lwjgl.opengl.GL32;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
@@ -32,7 +35,7 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
* @author James Seibel
* @version 11-20-2021
*/
public class GLVertexBuffer extends GLBuffer
public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
{
/**
* When uploading to a buffer that is too small, recreate it this many times
@@ -40,17 +43,61 @@ public class GLVertexBuffer extends GLBuffer
*/
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)
//=============//
// constructor //
//=============//
//region
public GLVertexBuffer() { this(GLProxy.getInstance().getGpuUploadMethod() == EDhApiGpuUploadMethod.BUFFER_STORAGE); }
public GLVertexBuffer(boolean isBufferStorage) { super(isBufferStorage); }
//endregion
//======================//
// uploading/destroying //
//======================//
//region
@Override
public int getBufferBindingTarget() { return GL32.GL_ARRAY_BUFFER; }
@Override
public void upload(ByteBuffer buffer, int vertexCount)
{
super(isBufferStorage);
EDhApiGpuUploadMethod uploadMethod = GLProxy.getInstance().getGpuUploadMethod();
int maxBufferSize = LodQuadBuilder.getMaxBufferByteSize();
this.uploadBuffer(buffer, vertexCount, uploadMethod, maxBufferSize);
}
/**
* 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 vertexCount, EDhApiGpuUploadMethod uploadMethod, int maxExpansionSize)
{
if (vertexCount < 0)
{
throw new IllegalArgumentException("vertexCount is negative!");
}
// If size is zero, just ignore it.
if (byteBuffer.limit() - byteBuffer.position() != 0)
{
boolean useBuffStorage = uploadMethod.useBufferStorage;
super.uploadBuffer(byteBuffer, uploadMethod, maxExpansionSize, useBuffStorage ? 0 : GL32.GL_STATIC_DRAW);
}
this.vertexCount = vertexCount;
}
@Override
public void close() { this.destroyAsync(); }
@Override
public void destroyAsync()
{
@@ -58,31 +105,8 @@ public class GLVertexBuffer extends GLBuffer
this.vertexCount = 0;
}
@Override
public int getBufferBindingTarget() { return GL32.GL_ARRAY_BUFFER; }
//endregion
/**
* 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;
}
}
@@ -11,9 +11,6 @@ public class DhFramebuffer implements IDhApiFramebuffer
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
private final Int2IntMap attachments;
private final int maxDrawBuffers;
private final int maxColorAttachments;
private boolean hasDepthAttachment;
private int id;
@@ -27,9 +24,6 @@ public class DhFramebuffer implements IDhApiFramebuffer
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. */
@@ -38,9 +32,6 @@ public class DhFramebuffer implements IDhApiFramebuffer
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;
}
@@ -56,8 +47,6 @@ public class DhFramebuffer implements IDhApiFramebuffer
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
@@ -69,46 +58,6 @@ public class DhFramebuffer implements IDhApiFramebuffer
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()
{
@@ -119,10 +68,6 @@ public class DhFramebuffer implements IDhApiFramebuffer
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()
{
@@ -19,6 +19,8 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.AbstractVertexAttribute;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.VertexPointer;
import org.lwjgl.opengl.GL32;
@@ -34,22 +36,26 @@ public class ScreenQuad
{
public static ScreenQuad INSTANCE = new ScreenQuad();
private static final float[] box_vertices = {
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 //
//=============//
//region
private ScreenQuad() { }
@@ -68,29 +74,43 @@ public class ScreenQuad
// Framebuffer
this.createBuffer();
}
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);
}
//endregion
//===========//
// rendering //
//===========//
//region
public void render()
{
this.init();
//this.boxBuffer.bind();
this.boxBuffer.bind();
this.va.bind();
//this.va.bindBufferToAllBindingPoints(this.boxBuffer.getId());
this.va.bindBufferToAllBindingPoints(this.boxBuffer.getId());
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
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);
}
//endregion
}
@@ -19,19 +19,18 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.apply;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLState;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.logging.DhLogger;
import org.lwjgl.opengl.GL32;
/**
* Copies {@link BlazeLodRenderer}'s currently active color and depth texture to Minecraft's framebuffer.
* Copies {@link com.seibel.distanthorizons.core.render.renderer.LodRenderer}'s currently active color and depth texture to Minecraft's framebuffer.
*/
public class DhApplyShader extends AbstractShaderRenderer
{
@@ -118,11 +117,11 @@ public class DhApplyShader extends AbstractShaderRenderer
//GLMC.glBlendFunc(GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveColorTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveColorTextureId());
GL32.glUniform1i(this.gDhColorTextureUniform, 0);
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveDepthTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId());
GL32.glUniform1i(this.gDepthMapUniform, 1);
// Copy to MC's framebuffer
@@ -142,7 +141,7 @@ public class DhApplyShader extends AbstractShaderRenderer
return;
}
int dhFrameBufferId = BlazeLodRenderer.INSTANCE.getActiveFramebufferId();
int dhFrameBufferId = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveFramebufferId();
if (dhFrameBufferId == -1)
{
return;
@@ -162,20 +161,15 @@ public class DhApplyShader extends AbstractShaderRenderer
// 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
// but it also resolves some other issues, so it's likely not an issue
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(BlazeLodRenderer.INSTANCE.getActiveColorTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveColorTextureId());
GL32.glUniform1i(this.gDhColorTextureUniform, 0);
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveDepthTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId());
GL32.glUniform1i(this.gDepthMapUniform, 1);
@@ -21,11 +21,8 @@ package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.VanillaFadeRenderer;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.lwjgl.opengl.GL32;
/**
@@ -35,9 +32,9 @@ import org.lwjgl.opengl.GL32;
* {@link VanillaFadeRenderer} - Parent to this shader. <br>
* {@link VanillaFadeShader} - draws the Fade texture. <br>
*/
public class FadeApplyShader extends AbstractShaderRenderer
public class DhFarFadeApplyShader extends AbstractShaderRenderer
{
public static FadeApplyShader INSTANCE = new FadeApplyShader();
public static DhFarFadeApplyShader INSTANCE = new DhFarFadeApplyShader();
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
@@ -19,29 +19,29 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
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.BlazeLodRenderer;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.render.RenderParams;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhFarFadeRenderer;
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>
* Handles fading MC and DH together via {@link DhFarFadeShader} and {@link DhFarFadeApplyShader}. <br><br>
*
* {@link DhFadeShader} - draws the Fade to a texture. <br>
* {@link FadeApplyShader} - draws the Fade texture to DH's framebuffer. <br>
* {@link DhFarFadeShader} - draws the Fade to a texture. <br>
* {@link DhFarFadeApplyShader} - draws the Fade texture to DH's framebuffer. <br>
*/
public class DhFadeRenderer
public class DhFarFadeRenderer implements IDhFarFadeRenderer
{
public static DhFadeRenderer INSTANCE = new DhFadeRenderer();
public static DhFarFadeRenderer INSTANCE = new DhFarFadeRenderer();
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
@@ -61,16 +61,17 @@ public class DhFadeRenderer
//=============//
// constructor //
//=============//
//region
private DhFadeRenderer() { }
private DhFarFadeRenderer() { }
public void init()
{
if (this.init) return;
this.init = true;
DhFadeShader.INSTANCE.init();
FadeApplyShader.INSTANCE.init();
DhFarFadeShader.INSTANCE.init();
DhFarFadeApplyShader.INSTANCE.init();
}
private void createFramebuffer(int width, int height)
@@ -107,17 +108,21 @@ public class DhFadeRenderer
}
//endregion
//========//
// render //
//========//
//region
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
@Override
public void render(RenderParams renderParams)
{
try
{
profiler.push("Fade Generate");
//profiler.push("Fade Generate");
this.init();
@@ -132,19 +137,16 @@ public class DhFadeRenderer
}
DhFadeShader.INSTANCE.frameBuffer = this.fadeFramebuffer;
DhFadeShader.INSTANCE.setProjectionMatrix(mcModelViewMatrix, mcProjectionMatrix);
DhFadeShader.INSTANCE.render(partialTicks);
DhFarFadeShader.INSTANCE.frameBuffer = this.fadeFramebuffer;
DhFarFadeShader.INSTANCE.setProjectionMatrix(renderParams.mcModelViewMatrix, renderParams.mcProjectionMatrix);
DhFarFadeShader.INSTANCE.render(0.0f);
// restored so we can write the fade texture to the main frame buffer
//mcState.restore();
//profiler.popPush("Fade Apply");
profiler.popPush("Fade Apply");
FadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
FadeApplyShader.INSTANCE.readFramebuffer = DhFadeShader.INSTANCE.frameBuffer;
FadeApplyShader.INSTANCE.drawFramebuffer = BlazeLodRenderer.INSTANCE.getActiveFramebufferId();
FadeApplyShader.INSTANCE.render(partialTicks);
DhFarFadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
DhFarFadeApplyShader.INSTANCE.readFramebuffer = DhFarFadeShader.INSTANCE.frameBuffer;
DhFarFadeApplyShader.INSTANCE.drawFramebuffer = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveFramebufferId();
DhFarFadeApplyShader.INSTANCE.render(0.0f);
}
catch (Exception e)
{
@@ -152,10 +154,12 @@ public class DhFadeRenderer
}
finally
{
profiler.pop();
//profiler.pop();
}
}
//emdregion
}
@@ -19,20 +19,21 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.lwjgl.opengl.GL32;
public class DhFadeShader extends AbstractShaderRenderer
public class DhFarFadeShader extends AbstractShaderRenderer
{
public static DhFadeShader INSTANCE = new DhFadeShader();
public static DhFarFadeShader INSTANCE = new DhFarFadeShader();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
@@ -61,7 +62,7 @@ public class DhFadeShader extends AbstractShaderRenderer
// constructor //
//=============//
public DhFadeShader() { }
public DhFarFadeShader() { }
@Override
public void onInit()
@@ -108,7 +109,7 @@ public class DhFadeShader extends AbstractShaderRenderer
}
public void setProjectionMatrix(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix)
public void setProjectionMatrix(DhApiMat4f mcModelViewMatrix, DhApiMat4f mcProjectionMatrix)
{
Mat4f dhProjectionMatrix = RenderUtil.createLodProjectionMatrix(mcProjectionMatrix);
Mat4f dhModelViewMatrix = RenderUtil.createLodModelViewMatrix(mcModelViewMatrix);
@@ -127,8 +128,8 @@ public class DhFadeShader extends AbstractShaderRenderer
@Override
protected void onRender()
{
int depthTextureId = BlazeLodRenderer.INSTANCE.getActiveDepthTextureId();
int colorTextureId = BlazeLodRenderer.INSTANCE.getActiveColorTextureId();
int depthTextureId = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId();
int colorTextureId = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveColorTextureId();
if (depthTextureId == -1
|| colorTextureId == -1)
@@ -17,20 +17,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing;
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLState;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade.DhFadeShader;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade.FadeApplyShader;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade.VanillaFadeShader;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhVanillaFadeRenderer;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.logging.DhLogger;
import org.lwjgl.opengl.GL32;
@@ -38,12 +36,12 @@ import org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
/**
* Handles fading MC and DH together via {@link VanillaFadeShader} and {@link FadeApplyShader}. <br><br>
* Handles fading MC and DH together via {@link VanillaFadeShader} and {@link DhFarFadeApplyShader}. <br><br>
*
* {@link VanillaFadeShader} - draws the Fade to a texture. <br>
* {@link FadeApplyShader} - draws the Fade texture to MC's FrameBuffer. <br>
* {@link DhFarFadeApplyShader} - draws the Fade texture to MC's FrameBuffer. <br>
*/
public class VanillaFadeRenderer
public class VanillaFadeRenderer implements IDhVanillaFadeRenderer
{
public static VanillaFadeRenderer INSTANCE = new VanillaFadeRenderer();
@@ -67,6 +65,7 @@ public class VanillaFadeRenderer
//=============//
// constructor //
//=============//
//region
private VanillaFadeRenderer() { }
@@ -76,7 +75,7 @@ public class VanillaFadeRenderer
this.init = true;
VanillaFadeShader.INSTANCE.init();
FadeApplyShader.INSTANCE.init();
DhFarFadeApplyShader.INSTANCE.init();
}
private void createFramebuffer(int width, int height)
@@ -114,15 +113,19 @@ public class VanillaFadeRenderer
}
}
//endregion
//========//
// render //
//========//
//region
@Override
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, IClientLevelWrapper level)
{
int depthTextureId = BlazeLodRenderer.INSTANCE.getActiveDepthTextureId();
int depthTextureId = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId();
if (depthTextureId == -1)
{
// the renderer hasn't been set up yet
@@ -165,10 +168,10 @@ public class VanillaFadeRenderer
{
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(0);
DhFarFadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
DhFarFadeApplyShader.INSTANCE.readFramebuffer = DhFarFadeShader.INSTANCE.frameBuffer;
DhFarFadeApplyShader.INSTANCE.drawFramebuffer = MC_RENDER.getTargetFramebuffer();
DhFarFadeApplyShader.INSTANCE.render(0);
}
profiler.pop();
@@ -179,10 +182,23 @@ public class VanillaFadeRenderer
}
}
//endregion
//================//
// base overrides //
//================//
//region
public void free()
{
VanillaFadeShader.INSTANCE.free();
FadeApplyShader.INSTANCE.free();
DhFarFadeApplyShader.INSTANCE.free();
}
//endregion
}
@@ -19,19 +19,19 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fade;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.lwjgl.opengl.GL32;
public class VanillaFadeShader extends AbstractShaderRenderer
public class VanillaFadeShader extends AbstractShaderRenderer
{
public static VanillaFadeShader INSTANCE = new VanillaFadeShader();
@@ -67,6 +67,7 @@ public class VanillaFadeShader extends AbstractShaderRenderer
//=============//
// constructor //
//=============//
//region
public VanillaFadeShader() { }
@@ -99,11 +100,14 @@ public class VanillaFadeShader extends AbstractShaderRenderer
}
//endregion
//=============//
// render prep //
//=============//
//region
@Override
protected void onApplyUniforms(float partialTicks)
@@ -148,17 +152,20 @@ public class VanillaFadeShader extends AbstractShaderRenderer
}
public void setLevelMaxHeight(int levelMaxHeight) { this.levelMaxHeight = levelMaxHeight; }
//endregion
//========//
// render //
//========//
//region
@Override
protected void onRender()
{
int depthTextureId = BlazeLodRenderer.INSTANCE.getActiveDepthTextureId();
int colorTextureId = BlazeLodRenderer.INSTANCE.getActiveColorTextureId();
int depthTextureId = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId();
int colorTextureId = DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveColorTextureId();
if (depthTextureId == -1
|| colorTextureId == -1)
@@ -195,4 +202,8 @@ public class VanillaFadeShader extends AbstractShaderRenderer
ScreenQuad.INSTANCE.render();
}
//endregion
}
@@ -19,11 +19,12 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fog;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLState;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhFogRenderer;
import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL43C;
@@ -35,9 +36,9 @@ import java.nio.ByteBuffer;
* {@link FogShader} - draws the Fog to a texture. <br>
* {@link FogApplyShader} - draws the Fog texture to DH's FrameBuffer. <br>
*/
public class FogRenderer
public class DhFogRenderer implements IDhFogRenderer
{
public static FogRenderer INSTANCE = new FogRenderer();
public static DhFogRenderer INSTANCE = new DhFogRenderer();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
@@ -57,7 +58,7 @@ public class FogRenderer
// constructor //
//=============//
private FogRenderer() { }
private DhFogRenderer() { }
public void init()
{
@@ -104,8 +105,10 @@ public class FogRenderer
//========//
// render //
//========//
//region
public void render(Mat4f modelViewProjectionMatrix, float partialTicks)
@Override
public void render(DhApiMat4f 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())
@@ -131,10 +134,23 @@ public class FogRenderer
}
}
//endregion
//================//
// base overrides //
//================//
//region
public void free()
{
FogShader.INSTANCE.free();
FogApplyShader.INSTANCE.free();
}
//endregion
}
@@ -19,11 +19,10 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fog;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import org.lwjgl.opengl.GL32;
@@ -31,7 +30,7 @@ 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 DhFogRenderer} - Parent to this shader. <br>
* {@link FogShader} - draws the Fog texture. <br>
*/
public class FogApplyShader extends AbstractShaderRenderer
@@ -82,7 +81,7 @@ public class FogApplyShader extends AbstractShaderRenderer
GL32.glUniform1i(this.colorTextureUniform, 0);
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveDepthTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId());
GL32.glUniform1i(this.depthTextureUniform, 1);
}
@@ -108,7 +107,7 @@ public class FogApplyShader extends AbstractShaderRenderer
// apply the rendered Fog to DH's framebuffer
GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, FogShader.INSTANCE.frameBuffer);
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, BlazeLodRenderer.INSTANCE.getActiveFramebufferId());
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveFramebufferId());
ScreenQuad.INSTANCE.render();
@@ -22,12 +22,13 @@ package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.fog;
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.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -244,7 +245,7 @@ public class FogShader extends AbstractShaderRenderer
return fogColor;
}
public void setProjectionMatrix(Mat4f modelViewProjectionMatrix)
public void setProjectionMatrix(DhApiMat4f modelViewProjectionMatrix)
{
this.inverseMvmProjMatrix = new Mat4f(modelViewProjectionMatrix);
this.inverseMvmProjMatrix.invert();
@@ -265,7 +266,7 @@ public class FogShader extends AbstractShaderRenderer
GLMC.disableBlend();
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveDepthTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId());
GL32.glUniform1i(this.uDepthMap, 0);
// this is necessary for MC 1.16 (IE Legacy OpenGL)
@@ -19,11 +19,12 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ssao;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.GLState;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhSsaoRenderer;
import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL43C;
@@ -35,9 +36,9 @@ import java.nio.ByteBuffer;
* {@link SSAOShader} - draws the SSAO to a texture. <br>
* {@link SSAOApplyShader} - draws the SSAO texture to DH's FrameBuffer. <br>
*/
public class SSAORenderer
public class DhSSAORenderer implements IDhSsaoRenderer
{
public static SSAORenderer INSTANCE = new SSAORenderer();
public static DhSSAORenderer INSTANCE = new DhSSAORenderer();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
@@ -57,7 +58,7 @@ public class SSAORenderer
// constructor //
//=============//
private SSAORenderer() { }
private DhSSAORenderer() { }
public void init()
{
@@ -105,8 +106,9 @@ public class SSAORenderer
//========//
// render //
//========//
//region
public void render(Mat4f projectionMatrix, float partialTicks)
public void render(DhApiMat4f dhProjectionMatrix)
{
try(GLState state = new GLState())
{
@@ -123,18 +125,31 @@ public class SSAORenderer
}
SSAOShader.INSTANCE.frameBuffer = this.ssaoFramebuffer;
SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix);
SSAOShader.INSTANCE.render(partialTicks);
SSAOShader.INSTANCE.setProjectionMatrix(dhProjectionMatrix);
SSAOShader.INSTANCE.render(0.0f);
SSAOApplyShader.INSTANCE.ssaoTexture = this.ssaoTexture;
SSAOApplyShader.INSTANCE.render(partialTicks);
SSAOApplyShader.INSTANCE.render(0.0f);
}
}
//endregion
//================//
// base overrides //
//================//
//region
public void free()
{
SSAOShader.INSTANCE.free();
SSAOApplyShader.INSTANCE.free();
}
//endregion
}
@@ -19,10 +19,10 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ssao;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.util.RenderUtil;
import org.lwjgl.opengl.GL32;
@@ -31,7 +31,7 @@ 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 DhSSAORenderer} - Parent to this shader. <br>
* {@link SSAOShader} - draws the SSAO texture. <br>
*/
public class SSAOApplyShader extends AbstractShaderRenderer
@@ -85,7 +85,7 @@ public class SSAOApplyShader extends AbstractShaderRenderer
protected void onApplyUniforms(float partialTicks)
{
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveDepthTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId());
GL32.glUniform1i(this.gDepthMapUniform, 0);
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
@@ -134,7 +134,7 @@ public class SSAOApplyShader extends AbstractShaderRenderer
// apply the rendered SSAO to the LODs
GLMC.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, SSAOShader.INSTANCE.frameBuffer);
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, BlazeLodRenderer.INSTANCE.getActiveFramebufferId());
GLMC.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveFramebufferId());
ScreenQuad.INSTANCE.render();
@@ -19,10 +19,11 @@
package com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ssao;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
import com.seibel.distanthorizons.common.render.nativeGl.DhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.ScreenQuad;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.render.renderer.BlazeLodRenderer;
import com.seibel.distanthorizons.common.render.nativeGl.util.AbstractShaderRenderer;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import org.lwjgl.opengl.GL32;
@@ -31,7 +32,7 @@ import org.lwjgl.opengl.GL32;
* Draws the SSAO to a texture. <br><br>
*
* See Also: <br>
* {@link SSAORenderer} - Parent to this shader. <br>
* {@link DhSSAORenderer} - Parent to this shader. <br>
* {@link SSAOApplyShader} - draws the SSAO texture to DH's FrameBuffer. <br>
*/
public class SSAOShader extends AbstractShaderRenderer
@@ -91,9 +92,9 @@ public class SSAOShader extends AbstractShaderRenderer
// render prep //
//=============//
public void setProjectionMatrix(Mat4f projectionMatrix)
public void setProjectionMatrix(DhApiMat4f projectionMatrix)
{
this.projection = projectionMatrix;
this.projection = new Mat4f(projectionMatrix);
this.invertedProjection = new Mat4f(projectionMatrix);
this.invertedProjection.invert();
@@ -132,7 +133,7 @@ public class SSAOShader extends AbstractShaderRenderer
GLMC.disableBlend();
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
GLMC.glBindTexture(BlazeLodRenderer.INSTANCE.getActiveDepthTextureId());
GLMC.glBindTexture(DhTerrainShaderProgram.OpenGlRenderState.INSTANCE.getActiveDepthTextureId());
ScreenQuad.INSTANCE.render();
}
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.common.render.nativeGl.test;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.common.render.nativeGl.postProcessing.apply.DhApplyShader;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -30,6 +31,7 @@ import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribut
import com.seibel.distanthorizons.common.render.nativeGl.glObject.vertexAttribute.VertexPointer;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTestTriangleRenderer;
import org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
@@ -40,14 +42,14 @@ import java.nio.ByteOrder;
* to the center of the screen to confirm DH's
* apply shader is running correctly
*/
public class GlTestRenderer
public class GlTestTriangleRenderer implements IDhTestTriangleRenderer
{
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
public static final GlTestRenderer INSTANCE = new GlTestRenderer();
public static final GlTestTriangleRenderer INSTANCE = new GlTestTriangleRenderer();
// Render a square with uv color
private static final float[] VERTICES =
@@ -72,7 +74,7 @@ public class GlTestRenderer
//=============//
//region
private GlTestRenderer() { }
private GlTestTriangleRenderer() { }
public void init()
{
@@ -108,7 +110,7 @@ public class GlTestRenderer
this.vbo = new GLVertexBuffer(false);
this.vbo.bind();
this.vbo.uploadBuffer(buffer, 4, EDhApiGpuUploadMethod.DATA, VERTICES.length * Float.BYTES);
this.vbo.uploadBuffer(buffer, 3, EDhApiGpuUploadMethod.DATA, VERTICES.length * Float.BYTES);
}
//endregion
@@ -130,8 +132,7 @@ public class GlTestRenderer
this.vbo.bind();
this.va.bindBufferToAllBindingPoints(this.vbo.getId());
// Render the square
GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 3);
}
//endregion
@@ -23,12 +23,12 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
import com.seibel.distanthorizons.common.render.blaze.BlazeDhRenderApiDefinition;
import com.seibel.distanthorizons.common.render.nativeGl.OpenGlDhRenderApiDefinition;
import com.seibel.distanthorizons.common.render.nativeGl.generic.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
import com.seibel.distanthorizons.common.wrappers.gui.ClassicConfigGUI;
import com.seibel.distanthorizons.common.wrappers.gui.LangWrapper;
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
@@ -93,9 +93,14 @@ public class MixinLightTexture
this.renderWrapper.updateLightmap(this.lightPixels, clientLevel);
#elif MC_VER < MC_1_21_5
this.renderWrapper.setLightmapId(this.target.getColorTextureId(), clientLevel);
#elif MC_VER <= MC_1_21_10
GlTexture glTexture = (GlTexture) this.texture;
this.renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
#else
//GlTexture glTexture = (GlTexture) this.texture;
//this.renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
// both options are available since the renderer can be changed to either Blaze3D or OpenGL
GlTexture glTexture = (GlTexture) this.texture;
this.renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
this.renderWrapper.setLightmapGpuTexture(this.texture, clientLevel);
#endif
}
@@ -85,9 +85,14 @@ public class MixinLightTexture
#elif MC_VER < MC_1_21_9
GlTexture glTexture = (GlTexture) this.texture;
renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
#elif MC_VER <= MC_1_21_10
GlTexture glTexture = (GlTexture) this.texture;
this.renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
#else
//int id = NeoforgeTextureUnwrapper.getGlTextureIdFromGpuTexture(this.texture);
//renderWrapper.setLightmapId(id, clientLevel);
// both options are available since the renderer can be changed to either Blaze3D or OpenGL
GlTexture glTexture = (GlTexture) this.texture;
renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
renderWrapper.setLightmapGpuTexture(this.texture, clientLevel);
#endif
}