diff --git a/src/main/java/com/seibel/lod/enums/GlProxyContext.java b/src/main/java/com/seibel/lod/enums/GlProxyContext.java
index 512b46c7b..f01c2c4b3 100644
--- a/src/main/java/com/seibel/lod/enums/GlProxyContext.java
+++ b/src/main/java/com/seibel/lod/enums/GlProxyContext.java
@@ -20,10 +20,10 @@
package com.seibel.lod.enums;
/**
- * Minecraft, Lod_Builder, None
+ * Minecraft, Lod_Builder, Lod_Render, None
*
* @author James Seibel
- * @version 10-1-2021
+ * @version 10-31-2021
*/
public enum GlProxyContext
{
@@ -33,6 +33,9 @@ public enum GlProxyContext
/** The context we send buffers to the GPU on */
LOD_BUILDER,
+ /** The context we draw LODs on */
+ LOD_RENDER,
+
/** used to un-bind threads */
NONE,
}
\ No newline at end of file
diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java
index 1294af5fd..b68701b76 100644
--- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java
+++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java
@@ -31,6 +31,7 @@ import com.seibel.lod.builders.worldGeneration.LodGenWorker;
import com.seibel.lod.builders.worldGeneration.LodWorldGenerator;
import com.seibel.lod.config.LodConfig;
import com.seibel.lod.enums.DistanceGenerationMode;
+import com.seibel.lod.enums.GlProxyContext;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodWorld;
import com.seibel.lod.objects.RegionPos;
@@ -55,18 +56,12 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
* This handles all events sent to the client,
* and is the starting point for most of the mod.
* @author James_Seibel
- * @version 10-23-2021
+ * @version 10-31-2021
*/
public class ClientProxy
{
public static final Logger LOGGER = LogManager.getLogger("LOD");
- /**
- * there is some setup that should only happen once,
- * once this is true that setup has completed
- */
- private boolean firstTimeSetupComplete = false;
-
private static final LodWorld lodWorld = new LodWorld();
private static final LodBuilder lodBuilder = new LodBuilder();
private static final LodBufferBuilder lodBufferBuilder = new LodBufferBuilder();
@@ -108,13 +103,11 @@ public class ClientProxy
// clear any out of date objects
mc.clearFrameObjectCache();
+ // make sure the GlProxy is created before the LodBufferBuilder needs it
+ GlProxy glProxy = GlProxy.getInstance();
+
try
{
- // only run the first time setup once
- if (!firstTimeSetupComplete)
- firstFrameSetup();
-
-
if (mc == null || mc.getPlayer() == null || lodWorld.getIsWorldNotLoaded())
return;
@@ -138,6 +131,7 @@ public class ClientProxy
profiler.pop(); // get out of "terrain"
profiler.push("LOD");
+ glProxy.setGlContext(GlProxyContext.LOD_RENDER);
renderer.drawLODs(lodDim, mcModelViewMatrix, partialTicks, mc.getProfiler());
profiler.pop(); // end LOD
@@ -154,6 +148,10 @@ public class ClientProxy
LOGGER.error("client proxy: " + e.getMessage());
e.printStackTrace();
}
+ finally
+ {
+ glProxy.setGlContext(GlProxyContext.MINECRAFT);
+ }
}
/** used in a development environment to change settings on the fly */
@@ -357,16 +355,6 @@ public class ClientProxy
DetailDistanceUtil.updateSettings();
}
-
- /** This event is called once during the first frame Minecraft renders in the world. */
- public void firstFrameSetup()
- {
- // make sure the GlProxy is created before the LodBufferBuilder needs it
- GlProxy.getInstance();
-
- firstTimeSetupComplete = true;
- }
-
/** this method reset some static data every time we change world */
private void resetMod()
{
diff --git a/src/main/java/com/seibel/lod/proxy/GlProxy.java b/src/main/java/com/seibel/lod/proxy/GlProxy.java
index 9aa4567eb..d1f49c3a4 100644
--- a/src/main/java/com/seibel/lod/proxy/GlProxy.java
+++ b/src/main/java/com/seibel/lod/proxy/GlProxy.java
@@ -21,6 +21,7 @@ package com.seibel.lod.proxy;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL;
+import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLCapabilities;
import com.mojang.blaze3d.systems.RenderSystem;
@@ -40,7 +41,7 @@ import com.seibel.lod.wrappers.MinecraftWrapper;
* https://gamedev.stackexchange.com/questions/91995/edit-vbo-data-or-create-a-new-one
*
* @author James Seibel
- * @version 10-23-2021
+ * @version 10-31-2021
*/
public class GlProxy
{
@@ -50,14 +51,19 @@ public class GlProxy
/** Minecraft's GLFW window */
public final long minecraftGlContext;
- /** Minecraft's GL context */
+ /** Minecraft's GL capabilities */
public final GLCapabilities minecraftGlCapabilities;
/** the LodBuilder's GLFW window */
public final long lodBuilderGlContext;
- /** the LodBuilder's GL context */
+ /** the LodBuilder's GL capabilities */
public final GLCapabilities lodBuilderGlCapabilities;
+ /** the LodRender's GLFW window */
+ public final long lodRenderGlContext;
+ /** the LodRender's GL capabilities */
+ public final GLCapabilities lodRenderGlCapabilities;
+
/**
* This is just used for debugging, hopefully it can be removed once
* the context switching is more stable.
@@ -93,44 +99,27 @@ public class GlProxy
minecraftGlContext = GLFW.glfwGetCurrentContext();
minecraftGlCapabilities = GL.getCapabilities();
- // create the LodBuilder's context
- // Hopefully this shouldn't cause any issues with other mods that need custom contexts
- // (although the number that do should be relatively few)
+ // context creation setup
+ GLFW.glfwDefaultWindowHints();
+ // make the context window invisible
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
+ // by default the context should get the highest available OpenGL version
+ // but this can be explicitly set for testing
+// GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
+// GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 5);
- // create an invisible window to hold the context
- lodBuilderGlCapabilities = GL.createCapabilities();
- lodBuilderGlContext = GLFW.glfwCreateWindow(640, 480, "LOD window", 0L, minecraftGlContext);
+
+ // create the LodRender context
+ lodRenderGlContext = GLFW.glfwCreateWindow(64, 48, "LOD Render Window", 0L, 0L); // create a window to hold the context
+ GLFW.glfwMakeContextCurrent(lodRenderGlContext);
+ lodRenderGlCapabilities = GL.createCapabilities();
+
+ // create the LodBuilder context
+ lodBuilderGlContext = GLFW.glfwCreateWindow(64, 48, "LOD Builder Window", 0L, lodRenderGlContext);
GLFW.glfwMakeContextCurrent(lodBuilderGlContext);
+ lodBuilderGlCapabilities = GL.createCapabilities();
- // Since this is called on the render thread, make sure the Minecraft context is used in the end
- GLFW.glfwMakeContextCurrent(minecraftGlContext);
- GL.setCapabilities(minecraftGlCapabilities);
-
-
-
-
- //==============================//
- // determine the OpenGL version //
- //==============================//
-
- bufferStorageSupported = minecraftGlCapabilities.glBufferStorage != 0;
- mapBufferRangeSupported = minecraftGlCapabilities.glMapBufferRange != 0;
-
- if (!minecraftGlCapabilities.OpenGL15)
- {
- String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GlProxy.class.getSimpleName() + " and discoverd this GPU doesn't support OpenGL 1.5 or greater.";
- mc.crashMinecraft(errorMessage + " Sorry I couldn't tell you sooner :(", new UnsupportedOperationException("This GPU doesn't support OpenGL 1.5 or greater."));
- }
-
- if (!bufferStorageSupported)
- {
- String fallBackVersion = mapBufferRangeSupported ? "3.0" : "1.5";
-
- ClientProxy.LOGGER.error("This GPU doesn't support Buffer Storage (OpenGL 4.5), falling back to OpenGL " + fallBackVersion + ". This may cause stuttering and reduced performance.");
- }
-
@@ -139,8 +128,31 @@ public class GlProxy
// get any GPU related capabilities //
//==================================//
- // see if this GPU can run fancy fog
- fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
+ ClientProxy.LOGGER.info("Lod Render OpenGL version [" + GL11.glGetString(GL11.GL_VERSION) + "].");
+
+ // crash the game if the GPU doesn't support OpenGL 1.5
+ if (!minecraftGlCapabilities.OpenGL15)
+ {
+ // Note: as of MC 1.17 this shouldn't happen since MC
+ // requires OpenGL 3.3, but just in case.
+ String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GlProxy.class.getSimpleName() + " and discoverd this GPU doesn't support OpenGL 1.5 or greater.";
+ mc.crashMinecraft(errorMessage + " Sorry I couldn't tell you sooner :(", new UnsupportedOperationException("This GPU doesn't support OpenGL 1.5 or greater."));
+ }
+
+
+
+ // get specific capabilities
+ bufferStorageSupported = lodBuilderGlCapabilities.glBufferStorage != 0;
+ mapBufferRangeSupported = lodBuilderGlCapabilities.glMapBufferRange != 0;
+ fancyFogAvailable = minecraftGlCapabilities.GL_NV_fog_distance;
+
+
+ // display the capabilities
+ if (!bufferStorageSupported)
+ {
+ String fallBackVersion = mapBufferRangeSupported ? "3.0" : "1.5";
+ ClientProxy.LOGGER.error("This GPU doesn't support Buffer Storage (OpenGL 4.5), falling back to OpenGL " + fallBackVersion + ". This may cause stuttering and reduced performance.");
+ }
if (!fancyFogAvailable)
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that the fancy fog option will not be available.");
@@ -148,6 +160,16 @@ public class GlProxy
+
+ //==========//
+ // clean up //
+ //==========//
+
+ // Since this is created on the render thread, make sure the Minecraft context is used in the end
+ GLFW.glfwMakeContextCurrent(minecraftGlContext);
+ GL.setCapabilities(minecraftGlCapabilities);
+
+
// GlProxy creation success
ClientProxy.LOGGER.error(GlProxy.class.getSimpleName() + " creation successful. OpenGL smiles upon you this day.");
}
@@ -163,12 +185,12 @@ public class GlProxy
{
GlProxyContext currentContext = getGlContext();
- // we don't have to change the context, we're already there.
+ // we don't have to change the context, we are already there.
if (currentContext == newContext)
return;
- long contextPointer = 0L;
+ long contextPointer;
GLCapabilities newGlCapabilities = null;
// get the pointer(s) for this context
@@ -178,6 +200,11 @@ public class GlProxy
contextPointer = lodBuilderGlContext;
newGlCapabilities = lodBuilderGlCapabilities;
break;
+
+ case LOD_RENDER:
+ contextPointer = lodRenderGlContext;
+ newGlCapabilities = lodRenderGlCapabilities;
+ break;
case MINECRAFT:
contextPointer = minecraftGlContext;
@@ -187,6 +214,7 @@ public class GlProxy
default: // default should never happen, it is just here to make the compiler happy
case NONE:
// 0L is equivalent to null
+ contextPointer = 0L;
break;
}
@@ -215,14 +243,19 @@ public class GlProxy
if (currentContext == lodBuilderGlContext)
return GlProxyContext.LOD_BUILDER;
+ else if (currentContext == lodRenderGlContext)
+ return GlProxyContext.LOD_RENDER;
else if (currentContext == minecraftGlContext)
return GlProxyContext.MINECRAFT;
else if (currentContext == 0L)
return GlProxyContext.NONE;
else
- // hopefully this shouldn't happen, but
- // at least now we will be notified if it does happen
- throw new IllegalStateException(Thread.currentThread().getName() + " has a unknown OpenGl context: [" + currentContext + "]. Minecraft context [" + minecraftGlContext + "], LodBuilder context [" + lodBuilderGlContext + "], no context [0].");
+ // hopefully this shouldn't happen
+ throw new IllegalStateException(Thread.currentThread().getName() +
+ " has a unknown OpenGl context: [" + currentContext + "]. "
+ + "Minecraft context [" + minecraftGlContext + "], "
+ + "LodBuilder context [" + lodBuilderGlContext + "], "
+ + "LodRender context [" + lodRenderGlContext + "], no context [0].");
}
diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java
index 45c419533..beb294735 100644
--- a/src/main/java/com/seibel/lod/render/LodRenderer.java
+++ b/src/main/java/com/seibel/lod/render/LodRenderer.java
@@ -63,7 +63,7 @@ import net.minecraft.world.phys.Vec3;
* This is where LODs are draw to the world.
*
* @author James Seibel
- * @version 10-25-2021
+ * @version 10-31-2021
*/
public class LodRenderer
{
@@ -180,14 +180,6 @@ public class LodRenderer
- //===============//
- // initial setup //
- //===============//
-
- profiler = newProfiler;
- profiler.push("LOD setup");
-
-
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
// starting here...
determineIfLodsShouldRegenerate(lodDim, partialTicks);
@@ -222,9 +214,18 @@ public class LodRenderer
}
- //===========================//
- // GL settings for rendering //
- //===========================//
+
+
+ //===============//
+ // initial setup //
+ //===============//
+
+ profiler = newProfiler;
+ profiler.push("LOD setup");
+
+ GlProxy glProxy = GlProxy.getInstance();
+
+
// set the required open GL settings
@@ -246,6 +247,7 @@ public class LodRenderer
GL15.glDisable(GL15.GL_LIGHT0);
GL15.glDisable(GL15.GL_LIGHT1);
+
// get the default projection matrix, so we can
// reset it after drawing the LODs
float[] mcProjMatrixRaw = new float[16];
@@ -255,6 +257,7 @@ public class LodRenderer
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
+
Matrix4f modelViewMatrix = offsetTheModelViewMatrix(mcModelViewMatrix, partialTicks);
vanillaBlockRenderedDistance = mc.getRenderDistance() * LodUtil.CHUNK_WIDTH;
// required for setupFog and setupProjectionMatrix
@@ -263,19 +266,26 @@ public class LodRenderer
else
farPlaneBlockDistance = LodConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH;
+
setupProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance, partialTicks);
+
// commented out until we can add shaders to handle lighting
//setupLighting(lodDim, partialTicks);
- NearFarFogSettings fogSettings = determineFogSettings();
// determine the current fog settings, so they can be
// reset after drawing the LODs
float defaultFogStartDist = GL15.glGetFloat(GL15.GL_FOG_START);
float defaultFogEndDist = GL15.glGetFloat(GL15.GL_FOG_END);
int defaultFogMode = GL15.glGetInteger(GL15.GL_FOG_MODE);
- int defaultFogDistance = GlProxy.getInstance().fancyFogAvailable ? GL15.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV) : -1;
+ int defaultFogDistance = glProxy.fancyFogAvailable ? GL15.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV) : -1;
+
+ NearFarFogSettings fogSettings = determineFogSettings();
+
+
+
+
//===========//
// rendering //
@@ -289,7 +299,7 @@ public class LodRenderer
Vector3f cameraDir = camera.getLookVector();
boolean cullingDisabled = LodConfig.CLIENT.graphics.advancedGraphicsOption.disableDirectionalCulling.get();
- boolean renderBufferStorage = LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.get() == GpuUploadMethod.BUFFER_STORAGE && GlProxy.getInstance().bufferStorageSupported;
+ boolean renderBufferStorage = LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.get() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
// used to determine what type of fog to render
int halfWidth = vbos.length / 2;
@@ -328,6 +338,9 @@ public class LodRenderer
}
+
+
+
//=========//
// cleanup //
//=========//
@@ -371,17 +384,17 @@ public class LodRenderer
LodUtil.LOD_VERTEX_FORMAT.setupBufferState();
// set up the model view matrix
- GL15.glPushMatrix();
- GL15.glLoadIdentity();
+// GL15.glPushMatrix(); // matrix code is only available in OpenGL 3.2 and lower
+// GL15.glLoadIdentity();
FloatBuffer matrixBuffer = FloatBuffer.allocate(16);
modelViewMatrix.store(matrixBuffer);
- GL15.glMultMatrixf(matrixBuffer);
+// GL15.glMultMatrixf(matrixBuffer);
GL15.glDrawArrays(GL15.GL_QUADS, 0, vertexCount);
// post draw cleanup
- GL15.glPopMatrix();
- GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
+// GL15.glPopMatrix();
+// GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
LodUtil.LOD_VERTEX_FORMAT.clearBufferState();
}