Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c5a2944d68 | |||
| 1405b7a433 | |||
| be00670b7e | |||
| 6f2c02d283 | |||
| 309526e7b9 |
@@ -7,7 +7,7 @@ allowing for an increased view distance without harming performance.
|
||||
Or in other words: this mod lets you see farther without turning your game into a slide show.\
|
||||
If you want to see a quick demo, check out a video covering the mod here:
|
||||
|
||||
[](https://www.youtube.com/watch?v=MDWcEvdUGUE)
|
||||
<a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank"></a>
|
||||
|
||||
|
||||
Forge version: 1.16.5-36.1.0
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
version = 'a1.5.0'
|
||||
version = 'a1.5.1'
|
||||
group = 'com.seibel.lod'
|
||||
archivesBaseName = 'Distant-Horizons_1.16.5'
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
* @author James Seibel
|
||||
* @version 7-3-2021
|
||||
*/
|
||||
@Mod(ModInfo.MODID)
|
||||
@Mod(ModInfo.ID)
|
||||
public class LodMain
|
||||
{
|
||||
public static LodMain instance;
|
||||
|
||||
@@ -22,12 +22,14 @@ package com.seibel.lod;
|
||||
/**
|
||||
* This file is similar to mcmod.info
|
||||
* @author James Seibel
|
||||
* @version 10-16-2021
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
public final class ModInfo
|
||||
{
|
||||
public static final String MODID = "lod";
|
||||
public static final String MODNAME = "DistantHorizons";
|
||||
public static final String MODAPI = "LodAPI";
|
||||
public static final String VERSION = "a1.5.0";
|
||||
public static final String ID = "lod";
|
||||
public static final String NAME = "DistantHorizons";
|
||||
/** Human readable version of MOD_NAME */
|
||||
public static final String READABLE_NAME = "Distant Horizons";
|
||||
public static final String API = "LodAPI";
|
||||
public static final String VERSION = "a1.5.1";
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL15C;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL45;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
@@ -40,6 +40,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.GlProxyContext;
|
||||
import com.seibel.lod.enums.GpuUploadMethod;
|
||||
import com.seibel.lod.enums.VanillaOverdraw;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
@@ -67,7 +68,7 @@ import net.minecraft.world.LightType;
|
||||
/**
|
||||
* This object is used to create NearFarBuffer objects.
|
||||
* @author James Seibel
|
||||
* @version 10-10-2021
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
@@ -109,14 +110,6 @@ public class LodBufferBuilder
|
||||
/** The OpenGL IDs of the storage buffers used by the drawableVbos */
|
||||
public int[][][] drawableStorageBufferIds;
|
||||
|
||||
/** used to debug how the buildableStorageBuffers are growing */
|
||||
public int[][][] bufferPreviousCapacity;
|
||||
/**
|
||||
* This is toggled when the buffers are swapped, so we only
|
||||
* display the expansion log for one set of buffers
|
||||
*/
|
||||
public boolean printExpansionLog = true;
|
||||
|
||||
/** Used when building new VBOs */
|
||||
public volatile VertexBuffer[][][] buildableVbos;
|
||||
/** VBOs that are sent over to the LodNodeRenderer */
|
||||
@@ -542,6 +535,8 @@ public class LodBufferBuilder
|
||||
*/
|
||||
public void setupBuffers(LodDimension lodDimension)
|
||||
{
|
||||
GlProxy glProxy = GlProxy.getInstance();
|
||||
|
||||
bufferLock.lock();
|
||||
int numbRegionsWide = lodDimension.getWidth();
|
||||
long regionMemoryRequired;
|
||||
@@ -554,10 +549,11 @@ public class LodBufferBuilder
|
||||
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
drawableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
buildableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
drawableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
bufferPreviousCapacity = new int[numbRegionsWide][numbRegionsWide][];
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
buildableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
drawableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
}
|
||||
|
||||
for (int x = 0; x < numbRegionsWide; x++)
|
||||
{
|
||||
@@ -579,9 +575,11 @@ public class LodBufferBuilder
|
||||
buildableVbos[x][z] = new VertexBuffer[numberOfBuffers];
|
||||
drawableVbos[x][z] = new VertexBuffer[numberOfBuffers];
|
||||
|
||||
buildableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
drawableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
bufferPreviousCapacity[x][z] = new int[numberOfBuffers];
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
buildableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
drawableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -591,16 +589,16 @@ public class LodBufferBuilder
|
||||
buildableVbos[x][z] = new VertexBuffer[1];
|
||||
drawableVbos[x][z] = new VertexBuffer[1];
|
||||
|
||||
buildableStorageBufferIds[x][z] = new int[1];
|
||||
drawableStorageBufferIds[x][z] = new int[1];
|
||||
bufferPreviousCapacity[x][z] = new int[1];
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
buildableStorageBufferIds[x][z] = new int[1];
|
||||
drawableStorageBufferIds[x][z] = new int[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < numberOfBuffersPerRegion[x][z]; i++)
|
||||
{
|
||||
bufferPreviousCapacity[x][z][i] = (int) regionMemoryRequired;
|
||||
|
||||
buildableBuffers[x][z][i] = new BufferBuilder((int) regionMemoryRequired);
|
||||
|
||||
buildableVbos[x][z][i] = new VertexBuffer(LodUtil.LOD_VERTEX_FORMAT);
|
||||
@@ -609,24 +607,27 @@ public class LodBufferBuilder
|
||||
|
||||
// create the initial mapped buffers (system memory)
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL45.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL45.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
// create the buffer storage (GPU memory)
|
||||
buildableStorageBufferIds[x][z][i] = GL45.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0); // the 0 flag means to create the storage in the GPUs memory
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
drawableStorageBufferIds[x][z][i] = GL45.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
// create the buffer storage (GPU memory)
|
||||
buildableStorageBufferIds[x][z][i] = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0); // the 0 flag means to create the storage in the GPUs memory
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
drawableStorageBufferIds[x][z][i] = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -665,8 +666,8 @@ public class LodBufferBuilder
|
||||
// was called from (if any).
|
||||
RenderSystem.recordRenderCall(() ->
|
||||
{
|
||||
GL45.glDeleteBuffers(buildableId);
|
||||
GL45.glDeleteBuffers(drawableId);
|
||||
GL15.glDeleteBuffers(buildableId);
|
||||
GL15.glDeleteBuffers(drawableId);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -708,9 +709,9 @@ public class LodBufferBuilder
|
||||
RenderSystem.recordRenderCall(() ->
|
||||
{
|
||||
if (buildableId != 0)
|
||||
GL45.glDeleteBuffers(buildableId);
|
||||
GL15.glDeleteBuffers(buildableId);
|
||||
if (drawableId != 0)
|
||||
GL45.glDeleteBuffers(drawableId);
|
||||
GL15.glDeleteBuffers(drawableId);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -773,6 +774,16 @@ public class LodBufferBuilder
|
||||
// this helps prevent interference (IE stuttering) with the Minecraft context.
|
||||
glProxy.setGlContext(GlProxyContext.LOD_BUILDER);
|
||||
|
||||
// determine the upload method
|
||||
GpuUploadMethod uploadMethod = LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.get();
|
||||
if (!glProxy.bufferStorageSupported && uploadMethod == GpuUploadMethod.BUFFER_STORAGE)
|
||||
{
|
||||
// if buffer storage isn't supported
|
||||
// default to SUB_DATA
|
||||
LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.set(GpuUploadMethod.SUB_DATA);
|
||||
uploadMethod = GpuUploadMethod.SUB_DATA;
|
||||
}
|
||||
|
||||
// actually upload the buffers
|
||||
for (int x = 0; x < buildableVbos.length; x++)
|
||||
{
|
||||
@@ -783,7 +794,7 @@ public class LodBufferBuilder
|
||||
for (int i = 0; i < buildableBuffers[x][z].length; i++)
|
||||
{
|
||||
ByteBuffer uploadBuffer = buildableBuffers[x][z][i].popNextBuffer().getSecond();
|
||||
vboUpload(buildableVbos[x][z][i], buildableStorageBufferIds[x][z][i], uploadBuffer, x, z, i, true);
|
||||
vboUpload(buildableVbos[x][z][i], buildableStorageBufferIds[x][z][i], uploadBuffer, true, uploadMethod);
|
||||
lodDim.setRegenRegionBufferByArrayIndex(x, z, false);
|
||||
}
|
||||
}
|
||||
@@ -807,11 +818,10 @@ public class LodBufferBuilder
|
||||
}
|
||||
}
|
||||
|
||||
/** Uploads the uploadBuffer into the VBO and then into GPU memory. */
|
||||
/** Uploads the uploadBuffer so the GPU can use it.
|
||||
* @param uploadMethod */
|
||||
private void vboUpload(VertexBuffer vbo, int storageBufferId, ByteBuffer uploadBuffer,
|
||||
int xVboIndex, int zVboIndex, int iVboIndex, boolean allowBufferExpansion)
|
||||
// x/zVboIndex are just used for the debugging console logging
|
||||
// and should be removed when the logger is removed.
|
||||
boolean allowBufferExpansion, GpuUploadMethod uploadMethod)
|
||||
{
|
||||
// this shouldn't happen, but just to be safe
|
||||
if (vbo.id != -1 && GlProxy.getInstance().getGlContext() == GlProxyContext.LOD_BUILDER)
|
||||
@@ -820,63 +830,98 @@ public class LodBufferBuilder
|
||||
vbo.vertexCount = (uploadBuffer.capacity() / vbo.format.getVertexSize());
|
||||
|
||||
|
||||
GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vbo.id);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
|
||||
try
|
||||
{
|
||||
// get a pointer to the buffer in system memory
|
||||
ByteBuffer vboBuffer = GL45.glMapBufferRange(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL45.GL_MAP_WRITE_BIT | GL45.GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
if (vboBuffer == null)
|
||||
// if possible use the faster buffer storage route
|
||||
if (uploadMethod == GpuUploadMethod.BUFFER_STORAGE)
|
||||
{
|
||||
int previousCapacity = uploadBuffer.capacity();
|
||||
|
||||
// only expand the buffers if the uploadBuffer actually
|
||||
// has something in it and expansion is allowed
|
||||
if (previousCapacity != 0 && allowBufferExpansion)
|
||||
// get a pointer to the buffer in system memory
|
||||
ByteBuffer vboBuffer = GL30.glMapBufferRange(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
if (vboBuffer == null)
|
||||
{
|
||||
// the buffer(s) aren't big enough, expand them.
|
||||
// This does cause lag/stuttering, so it should be avoided!
|
||||
int previousCapacity = uploadBuffer.capacity();
|
||||
|
||||
// expand the buffer in system memory
|
||||
GL45.glBufferData(GL45.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL45.GL_DYNAMIC_DRAW);
|
||||
GL45.glBufferSubData(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer);
|
||||
|
||||
// un-bind the system memory buffer
|
||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// expand the buffer storage
|
||||
GL45.glDeleteBuffers(storageBufferId);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, storageBufferId);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
// recursively try to upload into the newly created buffer storage
|
||||
// but don't recurse again if that fails
|
||||
// (we don't want an infinitely expanding buffer!)
|
||||
vboUpload(vbo, storageBufferId, uploadBuffer, xVboIndex, zVboIndex, iVboIndex, false);
|
||||
|
||||
|
||||
|
||||
/*if (printExpansionLog)
|
||||
// only expand the buffers if the uploadBuffer actually
|
||||
// has something in it and expansion is allowed
|
||||
if (previousCapacity != 0 && allowBufferExpansion)
|
||||
{
|
||||
// NOTE: this will display twice because we are double buffering
|
||||
// (using 1 buffer to generate into and one to draw)
|
||||
ClientProxy.LOGGER.info("vbo (" + xVboIndex + "," + zVboIndex + ") expanded: " + bufferPreviousCapacity[xVboIndex][zVboIndex][iVboIndex] + " -> " + (int)(uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER));
|
||||
bufferPreviousCapacity[xVboIndex][zVboIndex][iVboIndex] = (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER);
|
||||
}*/
|
||||
// the buffer(s) aren't big enough, expand them.
|
||||
// This does cause lag/stuttering, so it should be avoided!
|
||||
|
||||
// expand the buffer in system memory
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
|
||||
|
||||
// un-bind the system memory buffer
|
||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// expand the buffer storage
|
||||
GL15.glDeleteBuffers(storageBufferId);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, storageBufferId);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
// recursively try to upload into the newly created buffer storage
|
||||
// but don't recurse again if that fails
|
||||
// (we don't want an infinitely expanding buffer!)
|
||||
vboUpload(vbo, storageBufferId, uploadBuffer, false, uploadMethod);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// upload the buffer into system memory...
|
||||
vboBuffer.put(uploadBuffer);
|
||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
|
||||
// ...then upload into GPU memory
|
||||
// (uploading into GPU memory directly can only be done
|
||||
// through the glCopyBufferSubData/glCopyNamed... methods)
|
||||
GL45.glCopyNamedBufferSubData(vbo.id, storageBufferId, 0, 0, uploadBuffer.capacity());
|
||||
}
|
||||
}
|
||||
else if (uploadMethod == GpuUploadMethod.BUFFER_MAPPING)
|
||||
{
|
||||
// no stuttering but high GPU usage
|
||||
// stores everything in system memory instead of GPU memory
|
||||
// making rendering much slower.
|
||||
// Unless the user is running integrated graphics,
|
||||
// in that case this will actually work better than SUB_DATA.
|
||||
|
||||
|
||||
ByteBuffer vboBuffer = null;
|
||||
|
||||
// map buffer range is better since it can be explicitly unsynchronized
|
||||
if (GlProxy.getInstance().mapBufferRangeSupported)
|
||||
vboBuffer = GL30.glMapBufferRange(GL30.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
else
|
||||
vboBuffer = GL15.glMapBuffer(GL30.GL_ARRAY_BUFFER, uploadBuffer.capacity());
|
||||
|
||||
|
||||
if (vboBuffer == null)
|
||||
{
|
||||
GL15.glBufferData(GL45.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
vboBuffer.put(uploadBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// upload the buffer into system memory...
|
||||
vboBuffer.put(uploadBuffer);
|
||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
// hybrid subData/bufferData //
|
||||
// less stutter, low GPU usage
|
||||
|
||||
// ...then upload into GPU memory
|
||||
// (uploading into GPU memory directly can only be done
|
||||
// through the glCopyBufferSubData/glCopyNamed... methods)
|
||||
GL45.glCopyNamedBufferSubData(vbo.id, storageBufferId, 0, 0, uploadBuffer.capacity());
|
||||
//long size = GL31.glGetBufferParameteri64(GL15.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE); // hopefully just a int should be long enough
|
||||
long size = GL15.glGetBufferParameteri(GL15.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE);
|
||||
if (size < uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER)
|
||||
{
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_DYNAMIC_DRAW);
|
||||
}
|
||||
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -886,11 +931,14 @@ public class LodBufferBuilder
|
||||
}
|
||||
finally
|
||||
{
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
if (uploadMethod == GpuUploadMethod.BUFFER_MAPPING)
|
||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}//if vbo exists and in correct GL context
|
||||
}//vboUpload
|
||||
|
||||
/** Get the newly created VBOs */
|
||||
public VertexBuffersAndOffset getVertexBuffers()
|
||||
@@ -907,10 +955,6 @@ public class LodBufferBuilder
|
||||
drawableStorageBufferIds = buildableStorageBufferIds;
|
||||
buildableStorageBufferIds = tmpStorage;
|
||||
|
||||
// we only want to print the expansion log for
|
||||
// one set of buffers, not both
|
||||
printExpansionLog = !printExpansionLog;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
// the vbos have been swapped
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogDrawOverride;
|
||||
import com.seibel.lod.enums.GenerationPriority;
|
||||
import com.seibel.lod.enums.GpuUploadMethod;
|
||||
import com.seibel.lod.enums.HorizontalQuality;
|
||||
import com.seibel.lod.enums.HorizontalResolution;
|
||||
import com.seibel.lod.enums.HorizontalScale;
|
||||
@@ -51,7 +52,7 @@ import net.minecraftforge.fml.config.ModConfig;
|
||||
/**
|
||||
* This handles any configuration the user has access to.
|
||||
* @author James Seibel
|
||||
* @version 10-19-2021
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class LodConfig
|
||||
@@ -222,6 +223,8 @@ public class LodConfig
|
||||
|
||||
public final ForgeConfigSpec.EnumValue<VanillaOverdraw> vanillaOverdraw;
|
||||
|
||||
public final ForgeConfigSpec.EnumValue<GpuUploadMethod> gpuUploadMethod;
|
||||
|
||||
AdvancedGraphicsOption(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
|
||||
@@ -273,6 +276,17 @@ public class LodConfig
|
||||
+ " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n"
|
||||
+ " " + VanillaOverdraw.BORDER + ": LODs will render only on the border of vanilla chunks preventing only some holes in the world. \n")
|
||||
.defineEnum("Vanilla Overdraw", VanillaOverdraw.DYNAMIC);
|
||||
|
||||
gpuUploadMethod = builder
|
||||
.comment("\n\n"
|
||||
+ " What method should be used to upload geometry to the GPU? \n\\n"
|
||||
+ ""
|
||||
+ " " + GpuUploadMethod.BUFFER_STORAGE + ": Default if OpenGL 4.5 is supported. Fast rendering, no stuttering. \n"
|
||||
+ " " + GpuUploadMethod.SUB_DATA + ": Default if OpenGL 4.5 is NOT supported. Fast rendering but may stutter when uploading. \n"
|
||||
+ " " + GpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. Possibly better than " + GpuUploadMethod.SUB_DATA + " if using a integrated GPU. \n")
|
||||
.defineEnum("GPU Upload Method", GpuUploadMethod.BUFFER_STORAGE);
|
||||
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
@@ -519,7 +533,7 @@ public class LodConfig
|
||||
|
||||
|
||||
/** {@link Path} to the configuration file of this mod */
|
||||
private static final Path CONFIG_PATH = Paths.get("config", ModInfo.MODNAME + ".toml");
|
||||
private static final Path CONFIG_PATH = Paths.get("config", ModInfo.NAME + ".toml");
|
||||
|
||||
public static final ForgeConfigSpec CLIENT_SPEC;
|
||||
public static final Client CLIENT;
|
||||
@@ -540,13 +554,13 @@ public class LodConfig
|
||||
@SubscribeEvent
|
||||
public static void onLoad(final ModConfig.Loading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.MODNAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
LogManager.getLogger().debug(ModInfo.NAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onFileChange(final ModConfig.Reloading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.MODNAME, "Forge config just got changed on the file system!");
|
||||
LogManager.getLogger().debug(ModInfo.NAME, "Forge config just got changed on the file system!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.enums;
|
||||
|
||||
/**
|
||||
* Buffer_Storage, Sub_Data, Buffer_Mapping
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
public enum GpuUploadMethod
|
||||
{
|
||||
/** Default if OpenGL 4.5 is supported. Fast rendering, no stuttering. */
|
||||
BUFFER_STORAGE,
|
||||
|
||||
/** Default if OpenGL 4.5 is NOT supported. Fast rendering but may stutter when uploading. */
|
||||
SUB_DATA,
|
||||
|
||||
/** May end up storing buffers in System memory. Slower rendering but won't stutter when uploading. */
|
||||
BUFFER_MAPPING,
|
||||
}
|
||||
@@ -53,7 +53,7 @@ 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-15-2021
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
public class ClientProxy
|
||||
{
|
||||
@@ -176,6 +176,8 @@ public class ClientProxy
|
||||
// LodConfig.CLIENT.graphics.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
// LodConfig.CLIENT.graphics.shadingMode.set(ShadingMode.DARKEN_SIDES);
|
||||
// LodConfig.CLIENT.graphics.vanillaOverdraw.set(VanillaOverdraw.HALF);
|
||||
|
||||
// LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.set(GpuUploadMethod.BUFFER_STORAGE);
|
||||
|
||||
// LodConfig.CLIENT.worldGenerator.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
// LodConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.set(128);
|
||||
|
||||
@@ -24,7 +24,9 @@ import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.ModInfo;
|
||||
import com.seibel.lod.enums.GlProxyContext;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
/**
|
||||
* A singleton that holds references to different openGL contexts
|
||||
@@ -38,12 +40,14 @@ import com.seibel.lod.enums.GlProxyContext;
|
||||
* https://gamedev.stackexchange.com/questions/91995/edit-vbo-data-or-create-a-new-one <br><br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-2-2021
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
public class GlProxy
|
||||
{
|
||||
private static GlProxy instance = null;
|
||||
|
||||
private static MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
/** Minecraft's GLFW window */
|
||||
public final long minecraftGlContext;
|
||||
/** Minecraft's GL context */
|
||||
@@ -63,16 +67,22 @@ public class GlProxy
|
||||
/** Does this computer's GPU support fancy fog? */
|
||||
public final boolean fancyFogAvailable;
|
||||
|
||||
/** Requires OpenGL 4.5, and offers the best buffer uploading */
|
||||
public final boolean bufferStorageSupported;
|
||||
|
||||
/** Requires OpenGL 3.0 */
|
||||
public final boolean mapBufferRangeSupported;
|
||||
|
||||
|
||||
private GlProxy()
|
||||
{
|
||||
ClientProxy.LOGGER.error("Creating " + GlProxy.class.getSimpleName() + "... If this is the last message you see in the log there must have been a OpenGL error.");
|
||||
|
||||
// getting Minecraft's context has to be done on the render thread,
|
||||
// where the GL context is
|
||||
if (!RenderSystem.isOnRenderThread())
|
||||
throw new IllegalStateException(GlProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
@@ -101,6 +111,30 @@ public class GlProxy
|
||||
|
||||
|
||||
|
||||
//==============================//
|
||||
// determine the OpenGL version //
|
||||
//==============================//
|
||||
|
||||
bufferStorageSupported = minecraftGlCapabilities.OpenGL45;
|
||||
mapBufferRangeSupported = minecraftGlCapabilities.OpenGL30;
|
||||
|
||||
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 OpenGL 4.5, falling back to OpenGL " + fallBackVersion + ". This may cause stuttering and reduced performance.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================//
|
||||
// get any GPU related capabilities //
|
||||
//==================================//
|
||||
@@ -110,6 +144,12 @@ public class GlProxy
|
||||
|
||||
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.");
|
||||
|
||||
|
||||
|
||||
|
||||
// GlProxy creation success
|
||||
ClientProxy.LOGGER.error(GlProxy.class.getSimpleName() + " creation successful. OpenGL smiles upon you this day.");
|
||||
}
|
||||
|
||||
|
||||
@@ -188,15 +228,8 @@ public class GlProxy
|
||||
|
||||
public static GlProxy getInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new GlProxy();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (instance == null)
|
||||
instance = new GlProxy();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogDrawOverride;
|
||||
import com.seibel.lod.enums.FogQuality;
|
||||
import com.seibel.lod.enums.GpuUploadMethod;
|
||||
import com.seibel.lod.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.NearFarFogSettings;
|
||||
@@ -64,7 +65,7 @@ import net.minecraft.util.math.vector.Vector3d;
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-19-2021
|
||||
* @version 10-23-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
@@ -157,6 +158,7 @@ public class LodRenderer
|
||||
* @param mcMatrixStack This matrix stack should come straight from MC's renderChunkLayer (or future equivalent) method
|
||||
* @param partialTicks how far into the current tick this method was called.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void drawLODs(LodDimension lodDim, MatrixStack mcMatrixStack, float partialTicks, IProfiler newProfiler)
|
||||
{
|
||||
if (lodDim == null)
|
||||
@@ -276,6 +278,7 @@ public class LodRenderer
|
||||
Vector3d cameraDir = new Vector3d(renderInfo.getLookVector());
|
||||
|
||||
boolean cullingDisabled = LodConfig.CLIENT.graphics.advancedGraphicsOption.disableDirectionalCulling.get();
|
||||
boolean renderBufferStorage = LodConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.get() == GpuUploadMethod.BUFFER_STORAGE && GlProxy.getInstance().bufferStorageSupported;
|
||||
|
||||
// used to determine what type of fog to render
|
||||
int halfWidth = vbos.length / 2;
|
||||
@@ -292,6 +295,7 @@ public class LodRenderer
|
||||
RegionPos vboPos = new RegionPos(
|
||||
x + vboCenterRegionPos.x - (lodDim.getWidth() / 2),
|
||||
z + vboCenterRegionPos.z - (lodDim.getWidth() / 2));
|
||||
|
||||
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(renderInfo.getBlockPosition(), cameraDir, vboPos.blockPos()))
|
||||
{
|
||||
if ((x > halfWidth - quarterWidth && x < halfWidth + quarterWidth)
|
||||
@@ -301,10 +305,12 @@ public class LodRenderer
|
||||
setupFog(fogSettings.far.distance, fogSettings.far.quality);
|
||||
|
||||
|
||||
for (int i = 0; i < storageBufferIds[x][z].length; i++)
|
||||
{
|
||||
drawBuffer(vbos[x][z][i], storageBufferIds[x][z][i], modelViewMatrix);
|
||||
}
|
||||
if (storageBufferIds != null && renderBufferStorage)
|
||||
for (int i = 0; i < storageBufferIds[x][z].length; i++)
|
||||
drawStorageBuffer(vbos[x][z][i], storageBufferIds[x][z][i], modelViewMatrix);
|
||||
else
|
||||
for (int i = 0; i < vbos[x][z].length; i++)
|
||||
drawVertexBuffer(vbos[x][z][i], modelViewMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,12 +351,29 @@ public class LodRenderer
|
||||
|
||||
|
||||
/** This is where the actual drawing happens. */
|
||||
private void drawBuffer(VertexBuffer vbo, int bufferStorageId, Matrix4f modelViewMatrix)
|
||||
private void drawStorageBuffer(VertexBuffer vbo, int bufferStorageId, Matrix4f modelViewMatrix)
|
||||
{
|
||||
if (vbo == null)
|
||||
return;
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferStorageId);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferStorageId);
|
||||
// 0L is the starting pointer
|
||||
LodUtil.LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
LodUtil.LOD_VERTEX_FORMAT.clearBufferState();
|
||||
}
|
||||
|
||||
|
||||
/** This is where the actual drawing happens. */
|
||||
private void drawVertexBuffer(VertexBuffer vbo, Matrix4f modelViewMatrix)
|
||||
{
|
||||
if (vbo == null)
|
||||
return;
|
||||
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
|
||||
// 0L is the starting pointer
|
||||
LodUtil.LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
@@ -446,6 +469,7 @@ public class LodRenderer
|
||||
/**
|
||||
* Revert any changes that were made to the fog.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void cleanupFog(NearFarFogSettings fogSettings,
|
||||
float defaultFogStartDist, float defaultFogEndDist,
|
||||
int defaultFogMode, int defaultFogDistance)
|
||||
|
||||
@@ -22,6 +22,8 @@ package com.seibel.lod.wrappers;
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
|
||||
import com.seibel.lod.ModInfo;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import net.minecraft.client.GameSettings;
|
||||
@@ -36,6 +38,7 @@ import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.model.ModelManager;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
@@ -235,4 +238,20 @@ public class MinecraftWrapper
|
||||
{
|
||||
return mc.levelRenderer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Crashes Minecraft, displaying the given errorMessage <br> <br>
|
||||
* In the following format: <br>
|
||||
*
|
||||
* The game crashed whilst <strong>errorMessage</strong> <br>
|
||||
* Error: <strong>java.lang.ExceptionClass: exceptionErrorMessage</strong> <br>
|
||||
* Exit Code: -1 <br>
|
||||
*/
|
||||
public void crashMinecraft(String errorMessage, Throwable exception)
|
||||
{
|
||||
ClientProxy.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
|
||||
CrashReport report = new CrashReport(errorMessage, exception);
|
||||
Minecraft.crash(report);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ modId="lod" #mandatory
|
||||
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
#// see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version="a1.5.0" #mandatory
|
||||
version="a1.5.1" #mandatory
|
||||
|
||||
#// A display name for the mod
|
||||
displayName="Distant Horizons" #mandatory
|
||||
|
||||
Reference in New Issue
Block a user