Renderer rework completed

The renderer rework is done. Fixed some non-issues and optimized away
some bind() calls. Also added some FIXME comments to some place that I
noticed needs to be fixed.
This commit is contained in:
tom lee
2021-12-16 00:12:22 +08:00
parent 5709a4c660
commit 244ead9451
11 changed files with 192 additions and 236 deletions
@@ -160,8 +160,8 @@ public class EventApi
// prevent issues related to the buffer builder
// breaking or retaining previous data when changing worlds.
ClientApi.renderer.markForCleanup();
ClientApi.renderer.destroyBuffers();
ClientApi.renderer.requestCleanup();
recalculateWidths = true;
// TODO: Check if after the refactoring, is this still needed
ClientApi.renderer = new LodRenderer(ApiShared.lodBufferBuilderFactory);
@@ -316,6 +316,8 @@ public class LodBufferBuilderFactory
// keep a local version, so we don't have to worry about indexOutOfBounds Exceptions
// if it changes in the LodRenderer while we are working here
// FIXME: THIS IS NOT HOW IT WORKS! We also can't just loop and copy it. Think of an
// idea to fix this!
boolean[][] vanillaRenderedChunks = renderer.vanillaRenderedChunks;
short gameChunkRenderDistance = (short) (vanillaRenderedChunks.length / 2 - 1);
@@ -331,6 +333,7 @@ public class LodBufferBuilderFactory
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkX;
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkZ;
// FIXME: We don't need to ignore rendered chunks! Just build it and leave it for the renderer to decide!
//We don't want to render this fake block if
//The block is inside the render distance with, is not bigger than a chunk and is positioned in a chunk set as vanilla rendered
//
@@ -796,14 +799,7 @@ public class LodBufferBuilderFactory
glProxy.setGlContext(GLProxyContext.LOD_BUILDER);
// determine the upload method
GpuUploadMethod uploadMethod = CONFIG.client().advanced().buffers().getGpuUploadMethod();
if (!glProxy.bufferStorageSupported && uploadMethod == GpuUploadMethod.BUFFER_STORAGE)
{
// if buffer storage isn't supported
// default to SUB_DATA
CONFIG.client().advanced().buffers().setGpuUploadMethod(GpuUploadMethod.SUB_DATA);
uploadMethod = GpuUploadMethod.SUB_DATA;
}
GpuUploadMethod uploadMethod = glProxy.getGpuUploadMethod();
// determine the upload timeout
int uploadTimeoutInMS = CONFIG.client().advanced().buffers().getGpuUploadTimeoutInMilliseconds();
@@ -58,10 +58,10 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
public class GLProxy
{
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build());
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static GLProxy instance = null;
@@ -80,13 +80,20 @@ public class GLProxy
/** the proxyWorker's GL capabilities */
public final GLCapabilities proxyWorkerGlCapabilities;
/** Requires OpenGL 4.5, and offers the best buffer uploading */
/** Requires OpenGL 4.4, and offers the best buffer uploading */
public final boolean bufferStorageSupported;
public final boolean openGL43VertexAttributeSupported;
/** Requires OpenGL 4.5 */
public final boolean namedObjectSupported;
/** Requires OpenGL 4.3 */
public final boolean VertexAttributeBufferBindingSupported;
/** Requires OpenGL 3.0 */
public final boolean mapBufferRangeSupported;
/** Requires OpenGL 3.0, which will current min requirement as 3.3, should always be true */
@Deprecated
public final boolean mapBufferRangeSupported = true;
private final GpuUploadMethod preferredUploadMethod;
@@ -113,7 +120,15 @@ public class GLProxy
// get Minecraft's context
minecraftGlContext = GLFW.glfwGetCurrentContext();
minecraftGlCapabilities = GL.getCapabilities();
// crash the game if the GPU doesn't support OpenGL 3.3
if (!minecraftGlCapabilities.OpenGL33)
{
// Note: as of MC 1.17 this shouldn't happen since MC
// requires OpenGL 3.3, but for older MC version this will warn the player.
String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GLProxy.class.getSimpleName() + " and discovered this GPU doesn't support OpenGL 3.3 or greater.";
MC.crashMinecraft(errorMessage + " Sorry I couldn't tell you sooner :(", new UnsupportedOperationException("This GPU doesn't support OpenGL 3.3 or greater."));
}
// context creation setup
GLFW.glfwDefaultWindowHints();
@@ -124,7 +139,6 @@ public class GLProxy
// GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
// GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 5);
// create the LodBuilder context
lodBuilderGlContext = GLFW.glfwCreateWindow(64, 48, "LOD Builder Window", 0L, minecraftGlContext);
GLFW.glfwMakeContextCurrent(lodBuilderGlContext);
@@ -135,7 +149,12 @@ public class GLProxy
proxyWorkerGlContext = GLFW.glfwCreateWindow(64, 48, "LOD proxy worker Window", 0L, minecraftGlContext);
GLFW.glfwMakeContextCurrent(proxyWorkerGlContext);
proxyWorkerGlCapabilities = GL.createCapabilities();
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
VertexAttributeBufferBindingSupported = minecraftGlCapabilities.glBindVertexBuffer != 0L; // Nullptr
// Check if we can use the named version of all calls, which is available in GL4.5 or after
namedObjectSupported = minecraftGlCapabilities.glNamedBufferData != 0L; //Nullptr
//==================================//
// get any GPU related capabilities //
@@ -145,66 +164,31 @@ public class GLProxy
ClientApi.LOGGER.info("Lod Render OpenGL version [" + GL11.glGetString(GL11.GL_VERSION) + "].");
// crash the game if the GPU doesn't support OpenGL 2.0
if (!minecraftGlCapabilities.OpenGL20)
{
// 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 2.0 or greater.";
MC.crashMinecraft(errorMessage + " Sorry I couldn't tell you sooner :(", new UnsupportedOperationException("This GPU doesn't support OpenGL 2.0 or greater."));
}
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
openGL43VertexAttributeSupported = minecraftGlCapabilities.OpenGL43;
// get specific capabilities
bufferStorageSupported = lodBuilderGlCapabilities.glBufferStorage != 0;
mapBufferRangeSupported = lodBuilderGlCapabilities.glMapBufferRange != 0;
// Check if we can use the Buffer Storage, which is available in GL4.4 or after
bufferStorageSupported = lodBuilderGlCapabilities.glBufferStorage != 0L; // Nullptr
// display the capabilities
if (!bufferStorageSupported)
{
String fallBackVersion = mapBufferRangeSupported ? "3.0" : "1.5";
ClientApi.LOGGER.warn("This GPU doesn't support Buffer Storage (OpenGL 4.5), falling back to OpenGL " + fallBackVersion + ". This may cause stuttering and reduced performance.");
ClientApi.LOGGER.warn("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods.");
}
// if using AUTO gpuUpload
// determine a good default for the GPU
if (CONFIG.client().advanced().buffers().getGpuUploadMethod() == GpuUploadMethod.AUTO)
String vendor = GL15.glGetString(GL15.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION"
if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE"))
{
GpuUploadMethod uploadMethod;
String vendor = GL15.glGetString(GL15.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION"
if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE"))
{
// NVIDIA card
if (bufferStorageSupported)
{
uploadMethod = GpuUploadMethod.BUFFER_STORAGE;
}
else
{
uploadMethod = GpuUploadMethod.SUB_DATA;
}
}
else
{
// AMD or Intel card
if (mapBufferRangeSupported)
{
uploadMethod = GpuUploadMethod.BUFFER_MAPPING;
}
else
{
uploadMethod = GpuUploadMethod.DATA;
}
}
CONFIG.client().advanced().buffers().setGpuUploadMethod(uploadMethod);
ClientApi.LOGGER.info("GPU Vendor [" + vendor + "], Upload method set to [" + uploadMethod + "].");
// NVIDIA card
preferredUploadMethod = bufferStorageSupported ? GpuUploadMethod.BUFFER_STORAGE : GpuUploadMethod.SUB_DATA;
}
else
{
// AMD or Intel card
preferredUploadMethod = GpuUploadMethod.BUFFER_MAPPING;
}
ClientApi.LOGGER.info("GPU Vendor [" + vendor + "], Preferred upload method is [" + preferredUploadMethod + "].");
//==========//
// clean up //
//==========//
@@ -296,6 +280,19 @@ public class GLProxy
return instance;
}
public GpuUploadMethod getGpuUploadMethod() {
GpuUploadMethod method = CONFIG.client().advanced().buffers().getGpuUploadMethod();
if (!bufferStorageSupported && method == GpuUploadMethod.BUFFER_STORAGE)
{
// if buffer storage isn't supported
// default to SUB_DATA
method = GpuUploadMethod.SUB_DATA;
}
return method == GpuUploadMethod.AUTO ? preferredUploadMethod : method;
}
/**
* Asynchronously calls the given runnable on proxy's OpenGL context.
* Useful for creating/destroying OpenGL objects in a thread
@@ -335,7 +332,7 @@ public class GLProxy
* This only works with Legacy OpenGL because James hasn't
* looking into a way for it to work with Modern OpenGL.
*/
public void disableLegacyFog()
public boolean disableLegacyFog()
{
// make sure this is a legacy OpenGL context
if (minecraftGlCapabilities.glFogf != 0)
@@ -348,7 +345,9 @@ public class GLProxy
GL11.glFogf(GL11.GL_FOG_START, 0.0f);
GL11.glFogf(GL11.GL_FOG_END, Float.MAX_VALUE);
GL11.glFogf(GL11.GL_FOG_DENSITY, 0.0f);
return true;
}
return false;
}
@@ -61,12 +61,11 @@ public class LodRenderProgram extends ShaderProgram {
public final int nearFogEndUniform;
public final int farFogStartUniform;
public final int farFogEndUniform;
// This will bind VertexAttribute
public LodRenderProgram() {
super(VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH, "fragColor");
super.bind();
posAttrib = getAttributeLocation("vPosition");
colAttrib = getAttributeLocation("color");
blockSkyLightAttrib = getAttributeLocation("blockSkyLight");
@@ -92,18 +91,16 @@ public class LodRenderProgram extends ShaderProgram {
// TODO: Add better use of the LODFormat thing
int vertexByteCount = LodUtil.LOD_VERTEX_FORMAT.getByteSize();
if (GLProxy.getInstance().openGL43VertexAttributeSupported)
vao = new VertexAttributePostGL43();
if (GLProxy.getInstance().VertexAttributeBufferBindingSupported)
vao = new VertexAttributePostGL43(); // also binds VertexAttribute
else
vao = new VertexAttributePreGL43();
vao.bind();
vao = new VertexAttributePreGL43(); // also binds VertexAttribute
//vao.bind();
vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addVec3Pointer(false));
vao.setVertexAttribute(0, colAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(4, true));
vao.setVertexAttribute(0, blockSkyLightAttrib, VertexAttribute.VertexPointer.addUnsignedBytePointer(false));
vao.setVertexAttribute(0, blockLightAttrib, VertexAttribute.VertexPointer.addUnsignedBytePointer(false));
vao.completeAndCheck(vertexByteCount);
//vao.unbind();
//super.unbind();
}
// Override ShaderProgram.bind()
@@ -128,7 +125,7 @@ public class LodRenderProgram extends ShaderProgram {
}
public void unbindVertexBuffer() {
vao.unbindBufferFromAllBindingPoint();
vao.unbindBuffersFromAllBindingPoint();
}
public void fillUniformData(Mat4f modelViewMatrix, Mat4f projectionMatrix, Vec3f cameraPos, Color fogColor, int skyLight, int lightmapBindPoint) {
@@ -22,9 +22,7 @@ package com.seibel.lod.core.render;
import java.awt.Color;
import java.util.HashSet;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL33;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
@@ -34,7 +32,6 @@ import com.seibel.lod.core.enums.config.GpuUploadMethod;
import com.seibel.lod.core.enums.rendering.DebugMode;
import com.seibel.lod.core.enums.rendering.FogColorMode;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.objects.math.Mat4f;
@@ -74,7 +71,6 @@ public class LodRenderer
// This tells us if the renderer is enabled or not. If in a world, it should be enabled.
private boolean isSetupComplete = false;
private volatile boolean markToCleanup = false;
/** This is used to generate the buildable buffers */
private final LodBufferBuilderFactory lodBufferBuilderFactory;
@@ -90,7 +86,6 @@ public class LodRenderer
// The shader program
LodRenderProgram shaderProgram = null;
LightmapTexture lightmapTexture = null;
private int vbosCenterX = 0;
private int vbosCenterZ = 0;
@@ -114,6 +109,7 @@ public class LodRenderer
*/
private volatile boolean partialRegen = false;
private volatile boolean fullRegen = true;
private volatile boolean markToCleanup = false;
/**
* This HashSet contains every chunk that Vanilla Minecraft
@@ -122,20 +118,16 @@ public class LodRenderer
public boolean[][] vanillaRenderedChunks;
public boolean vanillaRenderedChunksChanged;
public boolean vanillaRenderedChunksEmptySkip = false;
private boolean canVanillaFogBeDisabled = true;
public void requestCleanup() {markToCleanup = true;}
public LodRenderer(LodBufferBuilderFactory newLodNodeBufferBuilder)
{
lodBufferBuilderFactory = newLodNodeBufferBuilder;
}
public void markForCleanup() {
markToCleanup = true;
}
private LodDimension lastLodDimension = null;
/**
* Besides drawing the LODs this method also starts
* the async process of generating the Buffers that hold those LODs.
@@ -167,10 +159,14 @@ public class LodRenderer
return;
}
// get MC's shader program
int currentProgram = GL33.glGetInteger(GL33.GL_CURRENT_PROGRAM);
GLProxy glProxy = GLProxy.getInstance();
if (CONFIG.client().graphics().fogQuality().getDisableVanillaFog())
glProxy.disableLegacyFog();
if (canVanillaFogBeDisabled && CONFIG.client().graphics().fogQuality().getDisableVanillaFog())
if (!glProxy.disableLegacyFog())
if (!MC_RENDER.tryDisableVanillaFog())
canVanillaFogBeDisabled = false;
// TODO move the buffer regeneration logic into its own class (probably called in the client api instead)
// starting here...
@@ -214,11 +210,9 @@ public class LodRenderer
// FIXME: Currently, we check for last Lod Dimension so that we can trigger a cleanup() if dimension has changed
// The better thing to do is to call cleanup() on leaving dimensions in the EventApi, but only for client-side.
if (markToCleanup || (lastLodDimension != null && lodDim != lastLodDimension)) {
if (markToCleanup) {
markToCleanup = false;
cleanup(); // This will unset the isSetupComplete, causing a setup() call.
lastLodDimension = lodDim;
//fullRegen = true;
}
//===================//
@@ -227,28 +221,32 @@ public class LodRenderer
profiler.push("LOD draw setup");
int currentProgram = GL20.glGetInteger(GL20.GL_CURRENT_PROGRAM);
// Setup LodRenderProgram and the LightmapTexture if it has not yet been done
if (!isSetupComplete) setup();
/*---------Set GL State--------*/
// set the required open GL settings
if (CONFIG.client().advanced().debugging().getDebugMode() == DebugMode.SHOW_DETAIL_WIREFRAME)
GL15.glPolygonMode(GL15.GL_FRONT_AND_BACK, GL15.GL_LINE);
GL33.glPolygonMode(GL33.GL_FRONT_AND_BACK, GL33.GL_LINE);
else
GL15.glPolygonMode(GL15.GL_FRONT_AND_BACK, GL15.GL_FILL);
GL15.glEnable(GL15.GL_CULL_FACE);
GL15.glEnable(GL15.GL_DEPTH_TEST);
GL33.glPolygonMode(GL33.GL_FRONT_AND_BACK, GL33.GL_FILL);
GL33.glEnable(GL33.GL_CULL_FACE);
GL33.glEnable(GL33.GL_DEPTH_TEST);
// enable transparent rendering
GL15.glBlendFunc(GL15.GL_SRC_ALPHA, GL15.GL_ONE_MINUS_SRC_ALPHA);
GL15.glEnable(GL15.GL_BLEND);
GL33.glBlendFunc(GL33.GL_SRC_ALPHA, GL33.GL_ONE_MINUS_SRC_ALPHA);
GL33.glEnable(GL33.GL_BLEND);
// get MC's shader program
/*---------Bind required objects--------*/
// Setup LodRenderProgram and the LightmapTexture if it has not yet been done
// also binds LightmapTexture, VAO, and ShaderProgram
if (!isSetupComplete) {
setup();
} else {
shaderProgram.bind();
}
GL33.glActiveTexture(GL33.GL_TEXTURE0);
LightmapTexture lightmapTexture = new LightmapTexture();
/*---------Get required data--------*/
// Get the matrixs for rendering
Mat4f modelViewMatrix = translateModelViewMatrix(mcModelViewMatrix, partialTicks);
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
@@ -258,28 +256,17 @@ public class LodRenderer
farPlaneBlockDistance = Math.min(CONFIG.client().graphics().quality().getLodChunkRenderDistance(), LodUtil.CEILED_DIMENSION_MAX_RENDER_DISTANCE) * LodUtil.CHUNK_WIDTH;
else
farPlaneBlockDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * LodUtil.CHUNK_WIDTH;
Mat4f projectionMatrix = createProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance, farPlaneBlockDistance);
LodFogConfig fogSettings = new LodFogConfig(CONFIG, REFLECTION_HANDLER, farPlaneBlockDistance, vanillaBlockRenderedDistance);
//==============//
// shader setup //
//==============//
// Bind and update the lightmap data
GL20.glActiveTexture(GL20.GL_TEXTURE0);
shaderProgram.bind();
// Fill the uniform data. Note: GL_TEXTURE_2D == texture bindpoint 0
/*---------Fill uniform data--------*/
// Fill the uniform data. Note: GL33.GL_TEXTURE0 == texture bindpoint 0
shaderProgram.fillUniformData(modelViewMatrix, projectionMatrix, getTranslatedCameraPos(),
getFogColor(), (int) (MC.getSkyDarken(partialTicks) * 15), 0);
lightmapTexture = new LightmapTexture();
lightmapTexture.bind();
lightmapTexture.fillData(MC_RENDER.getLightmapTextureWidth(), MC_RENDER.getLightmapTextureHeight(), MC_RENDER.getLightmapPixels());
// Previous guy said fog setting may be different from region to region, but the fogSettings never changed... soooooo...
shaderProgram.fillUniformDataForFog(fogSettings);
// Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one.
lightmapTexture.fillData(MC_RENDER.getLightmapTextureWidth(), MC_RENDER.getLightmapTextureHeight(), MC_RENDER.getLightmapPixels());
//===========//
// rendering //
@@ -288,7 +275,7 @@ public class LodRenderer
profiler.popPush("LOD draw");
boolean cullingDisabled = CONFIG.client().graphics().advancedGraphics().getDisableDirectionalCulling();
boolean renderBufferStorage = CONFIG.client().advanced().buffers().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
boolean usingBufferStorage = glProxy.getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE;
// where the center of the buffers is (needed when culling regions)
// render each of the buffers
@@ -308,16 +295,12 @@ public class LodRenderer
int bufferId = 0;
for (int i = 0; i < vbos[x][z].length; i++)
{
bufferId = (storageBufferIds != null && renderBufferStorage) ? storageBufferIds[x][z][i] : vbos[x][z][i].id;
bufferId = (storageBufferIds != null && usingBufferStorage) ? storageBufferIds[x][z][i] : vbos[x][z][i].id;
if (bufferId==0) continue;
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferId);
shaderProgram.bind();
GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, bufferId);
shaderProgram.bindVertexBuffer(bufferId);
GL30.glDrawArrays(GL30.GL_TRIANGLES, 0, vbos[x][z][i].vertexCount);
//shaderProgram.unbindVertexBuffer();
GL33.glDrawArrays(GL33.GL_TRIANGLES, 0, vbos[x][z][i].vertexCount);
}
}
}
}
@@ -325,24 +308,23 @@ public class LodRenderer
//================//
// render cleanup //
//================//
// if this cleanup isn't done MC will crash
// when trying to render its own terrain
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
lightmapTexture.unbind();
shaderProgram.unbind();
lightmapTexture.free();
profiler.popPush("LOD cleanup");
GL15.glPolygonMode(GL15.GL_FRONT_AND_BACK, GL15.GL_FILL);
GL15.glDisable(GL15.GL_BLEND); // TODO: what should this be reset to?
// if this cleanup isn't done MC will crash
// when trying to render its own terrain
GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, 0);
shaderProgram.unbind();
lightmapTexture.free();
GL33.glPolygonMode(GL33.GL_FRONT_AND_BACK, GL33.GL_FILL);
GL33.glDisable(GL33.GL_BLEND); // TODO: what should this be reset to?
GL20.glUseProgram(currentProgram);
GL33.glUseProgram(currentProgram);
// clear the depth buffer so everything is drawn over the LODs
GL15.glClear(GL15.GL_DEPTH_BUFFER_BIT);
GL33.glClear(GL33.GL_DEPTH_BUFFER_BIT);
// end of internal LOD profiling
profiler.pop();
@@ -365,7 +347,6 @@ public class LodRenderer
isSetupComplete = true;
shaderProgram = new LodRenderProgram();
//lightmapTexture = new LightmapTexture();
}
/** Create all buffers that will be used. */
@@ -461,11 +442,7 @@ public class LodRenderer
}
isSetupComplete = false;
ClientApi.LOGGER.info("Renderer Cleanup Started");
//GLProxy.getInstance().setGlContext(GLProxyContext.LOD_BUILDER);
shaderProgram.free();
//lightmapTexture.free();
//GLProxy.getInstance().setGlContext(GLProxyContext.NONE);
ClientApi.LOGGER.info("Renderer Cleanup Complete");
}
@@ -554,46 +531,10 @@ public class LodRenderer
prevPlayerPosTime = newTime;
}
/*
// determine how far the lighting has to
// change in order to rebuild the buffers
// the max brightness is 1 and the minimum is 0.2
float skyBrightness = lodDim.dimension.hasSkyLight() ? MC.getSkyDarken(partialTicks) : 0.2f;
float minLightingDifference;
switch (CONFIG.client().advanced().buffers().getRebuildTimes())
{
case FREQUENT:
minLightingDifference = 0.025f;
break;
case NORMAL:
minLightingDifference = 0.05f;
break;
default:
case RARE:
minLightingDifference = 0.1f;
break;
}
// check if the lighting changed
if (Math.abs(skyBrightness - prevSkyBrightness) > minLightingDifference
// make sure the lighting gets to the max/minimum value
// (just in case the minLightingDifference is too large to notice the change)
|| (skyBrightness == 1.0f && prevSkyBrightness != 1.0f) // noon
|| (skyBrightness == 0.2f && prevSkyBrightness != 0.2f) // midnight
|| MC_RENDER.getGamma() != prevBrightness)
{
fullRegen = true;
prevBrightness = MC_RENDER.getGamma();
prevSkyBrightness = skyBrightness;
}*/
//================//
// partial regens //
//================//
// check if the vanilla rendered chunks changed
if (newTime - prevVanillaChunkTime > CONFIG.client().advanced().buffers().getRebuildTimes().renderedChunkTimeout)
{
@@ -605,7 +546,6 @@ public class LodRenderer
prevVanillaChunkTime = newTime;
}
// check if there is any newly generated terrain to show
if (newTime - prevChunkTime > CONFIG.client().advanced().buffers().getRebuildTimes().chunkChangeTimeout)
{
@@ -617,8 +557,6 @@ public class LodRenderer
prevChunkTime = newTime;
}
//==============//
// LOD skipping //
//==============//
@@ -660,5 +598,5 @@ public class LodRenderer
vanillaRenderedChunks = new boolean[vanillaRenderedChunksWidth][vanillaRenderedChunksWidth];
}
}
@@ -3,12 +3,8 @@ package com.seibel.lod.core.render.objects;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
public class LightmapTexture {
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
public final int id;
public int id;
public LightmapTexture() {
id = GL30.glGenTextures();
@@ -29,6 +25,9 @@ public class LightmapTexture {
// private int[] testArray;
public void fillData(int lightMapWidth, int lightMapHeight, int[] pixels) {
GL20.glDeleteTextures(id);
id = GL30.glGenTextures();
GL20.glBindTexture(GL20.GL_TEXTURE_2D, id);
if (pixels.length != lightMapWidth*lightMapHeight)
throw new RuntimeException("Lightmap Width*Height not equal to pixels provided!");
@@ -23,7 +23,6 @@ import java.awt.Color;
import java.nio.FloatBuffer;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.system.MemoryStack;
import com.seibel.lod.core.objects.math.Mat4f;
@@ -44,9 +43,10 @@ public class ShaderProgram
{
/** Stores the handle of the program. */
public final int id;
/** Creates a shader program. */
// FIXME: A better way to set the fragData output name
// TODO: A better way to set the fragData output name
/** Creates a shader program.
* This will bind ShaderProgram */
public ShaderProgram(String vert, String frag, String fragDataOutputName)
{
Shader vertShader = new Shader(GL20.GL_VERTEX_SHADER, vert, false);
@@ -68,13 +68,15 @@ public class ShaderProgram
free(); // important!
throw new RuntimeException(message);
}
GL20.glUseProgram(id); // This HAVE to be a direct call to prevent calling the overloaded version
}
/** Calls GL20.glUseProgram(this.id) */
/** This will bind ShaderProgram */
public void bind()
{
GL20.glUseProgram(id);
}
/** This will unbind ShaderProgram */
public void unbind() {
GL20.glUseProgram(0);
}
@@ -114,33 +116,39 @@ public class ShaderProgram
if (i==-1) throw new RuntimeException("Uniform name not found: "+name);
return i;
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, boolean value)
{
// This use -1 for false as that equals all one set
GL20.glUniform1i(location, value ? 1 : 0);
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, int value)
{
GL20.glUniform1i(location, value);
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, float value)
{
GL20.glUniform1f(location, value);
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, Vec3f value)
{
GL20.glUniform3f(location, value.x, value.y, value.z);
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, Vec3d value)
{
GL20.glUniform3f(location, (float) value.x, (float) value.y, (float) value.z);
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, Mat4f value)
{
try (MemoryStack stack = MemoryStack.stackPush())
@@ -151,7 +159,8 @@ public class ShaderProgram
}
}
/** Converts the color's RGBA values into values between 0 and 1. */
/** Converts the color's RGBA values into values between 0 and 1.
* Requires ShaderProgram binded. */
public void setUniform(int location, Color value)
{
GL20.glUniform4f(location, value.getRed() / 256.0f, value.getGreen() / 256.0f, value.getBlue() / 256.0f, value.getAlpha() / 256.0f);
@@ -23,8 +23,6 @@ import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import com.seibel.lod.core.api.ClientApi;
public abstract class VertexAttribute {
public static final class VertexPointer {
@@ -74,13 +72,18 @@ public abstract class VertexAttribute {
/** Stores the handle of the VertexAttribute. */
public final int id;
// This will bind VertexAttribute
protected VertexAttribute() {
id = GL30.glGenVertexArrays();
GL30.glBindVertexArray(id);
}
// This will bind VertexAttribute
public void bind() {
GL30.glBindVertexArray(id);
}
// This will unbind VertexAttribute
public void unbind() {
GL30.glBindVertexArray(0);
}
@@ -90,16 +93,16 @@ public abstract class VertexAttribute {
GL30.glDeleteVertexArrays(id);
}
// Requires Vao binded
// Requires VertexAttribute binded, VertexBuffer binded
public abstract void bindBufferToAllBindingPoint(int buffer);
// Requires Vao binded
// Requires VertexAttribute binded, VertexBuffer binded
public abstract void bindBufferToBindingPoint(int buffer, int bindingPoint);
// Requires Vao binded
public abstract void unbindBufferFromAllBindingPoint();
// Requires Vao binded
public abstract void unbindBufferFromBindingPoint(int bindingPoint);
// Requires Vao binded
// Requires VertexAttribute binded
public abstract void unbindBuffersFromAllBindingPoint();
// Requires VertexAttribute binded
public abstract void unbindBuffersFromBindingPoint(int bindingPoint);
// Requires VertexAttribute binded
public abstract void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute);
// Requires Vao binded
// Requires VertexAttribute binded
public abstract void completeAndCheck(int expectedStrideSize);
}
@@ -19,34 +19,40 @@ public final class VertexAttributePostGL43 extends VertexAttribute {
int numberOfBindingPoints = 0;
int strideSize = 0;
// This will bind VertexAttribute
public VertexAttributePostGL43() {
super();
super(); // also bind VertexAttribute
}
@Override
// Requires VertexAttribute binded, VertexBuffer binded
public void bindBufferToAllBindingPoint(int buffer) {
for (int i=0; i<numberOfBindingPoints; i++)
GL43.glBindVertexBuffer(i, buffer, 0, strideSize);
}
@Override
// Requires VertexAttribute binded, VertexBuffer binded
public void bindBufferToBindingPoint(int buffer, int bindingPoint) {
GL43.glBindVertexBuffer(bindingPoint, buffer, 0, strideSize);
}
@Override
public void unbindBufferFromAllBindingPoint() {
// Requires VertexAttribute binded
public void unbindBuffersFromAllBindingPoint() {
for (int i=0; i<numberOfBindingPoints; i++)
GL43.glBindVertexBuffer(i, 0, 0, 0);
}
@Override
public void unbindBufferFromBindingPoint(int bindingPoint) {
// Requires VertexAttribute binded
public void unbindBuffersFromBindingPoint(int bindingPoint) {
GL43.glBindVertexBuffer(bindingPoint, 0, 0, 0);
}
@Override
// Requires VertexAttribute binded
public void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute) {
GL43.glVertexAttribFormat(attributeIndex, attribute.elementCount, attribute.glType,
attribute.normalized, strideSize); // Here strideSize is new attrib offset
@@ -57,6 +63,7 @@ public final class VertexAttributePostGL43 extends VertexAttribute {
}
@Override
// Requires VertexAttribute binded
public void completeAndCheck(int expectedStrideSize) {
if (strideSize != expectedStrideSize) {
ClientApi.LOGGER.error("Vertex Attribute calculated stride size " + strideSize +
@@ -22,17 +22,17 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
TreeMap<Integer, TreeSet<Integer>> bindingPointsToIndexBuilder;
ArrayList<VertexPointer> pointersBuilder;
// This will bind VertexAttribute
public VertexAttributePreGL43() {
super();
super(); // also bind VertexAttribute
bindingPointsToIndexBuilder = new TreeMap<Integer, TreeSet<Integer>>();
pointersBuilder = new ArrayList<VertexPointer>();
}
@Override
// Requires VertexAttribute binded, VertexBuffer binded
public void bindBufferToAllBindingPoint(int buffer) {
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, buffer);
for (int i=0; i<pointers.length; i++)
GL20.glEnableVertexAttribArray(i);
@@ -45,10 +45,8 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
}
@Override
// Requires VertexAttribute binded, VertexBuffer binded
public void bindBufferToBindingPoint(int buffer, int bindingPoint) {
GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, buffer);
int[] toBind = bindingPointsToIndex[bindingPoint];
for (int i=0; i<toBind.length; i++)
@@ -63,13 +61,15 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
}
@Override
public void unbindBufferFromAllBindingPoint() {
// Requires VertexAttribute binded
public void unbindBuffersFromAllBindingPoint() {
for (int i=0; i<pointers.length; i++)
GL20.glDisableVertexAttribArray(i);
}
@Override
public void unbindBufferFromBindingPoint(int bindingPoint) {
// Requires VertexAttribute binded
public void unbindBuffersFromBindingPoint(int bindingPoint) {
int[] toBind = bindingPointsToIndex[bindingPoint];
for (int i=0; i<toBind.length; i++)
@@ -77,6 +77,7 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
}
@Override
// Requires VertexAttribute binded
public void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute) {
TreeSet<Integer> intArray = bindingPointsToIndexBuilder.get(bindingPoint);
if (intArray == null) {
@@ -94,6 +95,7 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
}
@Override
// Requires VertexAttribute binded
public void completeAndCheck(int expectedStrideSize) {
int maxBindPointNumber = bindingPointsToIndexBuilder.lastKey();
bindingPointsToIndex = new int[maxBindPointNumber+1][];
@@ -106,7 +108,6 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
}
});
pointers = pointersBuilder.toArray(new VertexPointer[pointersBuilder.size()]);
pointersOffset = new int[pointers.length];
pointersBuilder = null; // Release the builder
@@ -131,11 +132,12 @@ public final class VertexAttributePreGL43 extends VertexAttribute {
// Debug logging
ClientApi.LOGGER.info("Vertex Attribute Debug Data:");
ClientApi.LOGGER.info("AttributeIndex: ElementCount, glType, normalized, strideSize, offset");
for (int i=0; i< pointers.length; i++) {
VertexPointer pointer = pointers[i];
if (pointer==null) {
ClientApi.LOGGER.info(i + ": Null");
ClientApi.LOGGER.warn(i + ": Null!!!!");
continue;
}
ClientApi.LOGGER.info(i + ": "+pointer.elementCount+", "+
@@ -125,4 +125,10 @@ public interface IMinecraftRenderWrapper
int getLightmapTextureWidth();
/** @returns -1 if there was an issue getting the lightmap */
public int getLightmapGLFormat();
/** Try and disable vanilla fog. Return true if successful, or false if not able to.
* If we are still using legacy fog, this method will not be called. */
public default boolean tryDisableVanillaFog() {
return false;
}
}