partially add different context rendering
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package com.seibel.lod.builders;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -26,7 +27,10 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL15C;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.seibel.lod.builders.lodTemplates.Box;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.objects.DataPoint;
|
||||
@@ -36,6 +40,8 @@ import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.PosToRenderContainer;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.proxy.GlProxy;
|
||||
import com.seibel.lod.proxy.GlProxy.GlProxyContext;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
@@ -45,7 +51,6 @@ import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
|
||||
/**
|
||||
* This object is used to create NearFarBuffer objects.
|
||||
*
|
||||
@@ -57,76 +62,79 @@ public class LodBufferBuilder
|
||||
/**
|
||||
* This holds the thread used to generate new LODs off the main thread.
|
||||
*/
|
||||
private ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - main"));
|
||||
public static ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(LodBufferBuilder.class.getSimpleName() + " - main"));
|
||||
/**
|
||||
* This holds the threads used to generate buffers.
|
||||
*/
|
||||
private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfBufferBuilderThreads.get(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder"));
|
||||
|
||||
public static ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfBufferBuilderThreads.get(), new LodThreadFactory(LodBufferBuilder.class.getSimpleName() + " - builder"));
|
||||
|
||||
public volatile ByteBuffer clearByteBuffer;
|
||||
/**
|
||||
* The buffers that are used to create LODs using far fog
|
||||
*/
|
||||
public volatile BufferBuilder[][] buildableBuffers;
|
||||
|
||||
|
||||
/**
|
||||
* Used when building new VBOs
|
||||
*/
|
||||
public volatile VertexBuffer[][] buildableVbos;
|
||||
|
||||
|
||||
/**
|
||||
* VBOs that are sent over to the LodNodeRenderer
|
||||
*/
|
||||
public volatile VertexBuffer[][] drawableVbos;
|
||||
|
||||
|
||||
public GlProxyContext buildingContext = GlProxyContext.BUILDER;
|
||||
public GlProxyContext renderContext = GlProxyContext.RENDER;
|
||||
|
||||
/**
|
||||
* if this is true the LOD buffers are currently being
|
||||
* regenerated.
|
||||
*/
|
||||
public boolean generatingBuffers = false;
|
||||
|
||||
|
||||
/**
|
||||
* if this is true new LOD buffers have been generated
|
||||
* and are waiting to be swapped with the drawable buffers
|
||||
*/
|
||||
private boolean switchVbos = false;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Size of the buffer builders in bytes last time we created them
|
||||
*/
|
||||
public int previousBufferSize = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Width of the dimension in regions last time we created the buffers
|
||||
*/
|
||||
public int previousRegionWidth = 0;
|
||||
|
||||
|
||||
/**
|
||||
* this is used to prevent multiple threads creating, destroying, or using the buffers at the same time
|
||||
*/
|
||||
private ReentrantLock bufferLock = new ReentrantLock();
|
||||
|
||||
|
||||
private static final int NUMBER_OF_DIRECTION = 4;
|
||||
//in order -x, +x, -z, +z
|
||||
private static final int[][] ADJ_DIRECTION = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
|
||||
|
||||
private static final int[][] ADJ_DIRECTION = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
|
||||
|
||||
private volatile Box[][] boxCache;
|
||||
private volatile PosToRenderContainer[][] setsToRender;
|
||||
private volatile RegionPos center;
|
||||
|
||||
|
||||
/** This is the ChunkPos the player was at the last time the buffers were built.
|
||||
* IE the center of the buffers last time they were built */
|
||||
private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0,0);
|
||||
private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0,0);
|
||||
|
||||
|
||||
|
||||
private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0, 0);
|
||||
private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0, 0);
|
||||
|
||||
|
||||
|
||||
|
||||
public LodBufferBuilder()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread to asynchronously generate LOD buffers
|
||||
* centered around the given camera X and Z.
|
||||
@@ -137,65 +145,60 @@ public class LodBufferBuilder
|
||||
* swapped with the drawable buffers in the LodRenderer to be drawn.
|
||||
*/
|
||||
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
|
||||
BlockPos playerBlockPos, boolean fullRegen)
|
||||
BlockPos playerBlockPos, boolean fullRegen)
|
||||
{
|
||||
// only allow one generation process to happen at a time
|
||||
if (generatingBuffers)
|
||||
return;
|
||||
|
||||
|
||||
if (buildableBuffers == null)
|
||||
// setupBuffers hasn't been called yet
|
||||
return;
|
||||
|
||||
|
||||
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
ChunkPos playerChunkPos = new ChunkPos(playerBlockPos);
|
||||
BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition();
|
||||
|
||||
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
long treeStart = System.currentTimeMillis();
|
||||
long treeEnd = System.currentTimeMillis();
|
||||
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
|
||||
ArrayList<Callable<Boolean>> nodeToRenderThreads = new ArrayList<>(lodDim.regions.length * lodDim.regions.length);
|
||||
|
||||
|
||||
startBuffers(fullRegen, lodDim);
|
||||
|
||||
|
||||
// =====================//
|
||||
// RENDERING PART //
|
||||
// =====================//
|
||||
|
||||
|
||||
RegionPos playerRegionPos = new RegionPos(playerChunkPos);
|
||||
if (center == null)
|
||||
center = playerRegionPos;
|
||||
|
||||
|
||||
if (setsToRender == null)
|
||||
setsToRender = new PosToRenderContainer[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
|
||||
if (setsToRender.length != lodDim.regions.length)
|
||||
setsToRender = new PosToRenderContainer[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
|
||||
if (boxCache == null)
|
||||
boxCache = new Box[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
|
||||
if (boxCache.length != lodDim.regions.length)
|
||||
boxCache = new Box[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
|
||||
// this will be the center of the VBOs once they have been built
|
||||
buildableCenterChunkPos = playerChunkPos;
|
||||
|
||||
|
||||
for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++)
|
||||
{
|
||||
for (int zRegion = 0; zRegion < lodDim.regions.length; zRegion++)
|
||||
@@ -205,7 +208,7 @@ public class LodBufferBuilder
|
||||
RegionPos regionPos = new RegionPos(
|
||||
xRegion + lodDim.getCenterX() - Math.floorDiv(lodDim.getWidth(), 2),
|
||||
zRegion + lodDim.getCenterZ() - Math.floorDiv(lodDim.getWidth(), 2));
|
||||
|
||||
|
||||
// local position in the vbo and bufferBuilder arrays
|
||||
BufferBuilder currentBuffer = buildableBuffers[xRegion][zRegion];
|
||||
LodRegion region = lodDim.getRegion(regionPos.x, regionPos.z);
|
||||
@@ -220,26 +223,26 @@ public class LodBufferBuilder
|
||||
final int zR = zRegion;
|
||||
Callable<Boolean> dataToRenderThread = () ->
|
||||
{
|
||||
|
||||
|
||||
//previous setToRender chache
|
||||
if (setsToRender[xR][zR] == null)
|
||||
{
|
||||
setsToRender[xR][zR] = new PosToRenderContainer(minDetail, regionPos.x, regionPos.z);
|
||||
}
|
||||
|
||||
|
||||
if (boxCache[xR][zR] == null)
|
||||
{
|
||||
boxCache[xR][zR] = new Box();
|
||||
}
|
||||
PosToRenderContainer posToRender = setsToRender[xR][zR];
|
||||
posToRender.clear(minDetail, regionPos.x, regionPos.z);
|
||||
|
||||
|
||||
lodDim.getDataToRender(
|
||||
posToRender,
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
|
||||
|
||||
byte detailLevel;
|
||||
int posX;
|
||||
int posZ;
|
||||
@@ -259,9 +262,9 @@ public class LodBufferBuilder
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.x;
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.z;
|
||||
if (gameChunkRenderDistance >= Math.abs(chunkXdist)
|
||||
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
|
||||
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
|
||||
&& renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1])
|
||||
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
|
||||
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
|
||||
&& renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -271,24 +274,25 @@ public class LodBufferBuilder
|
||||
if (lodDim.doesDataExist(detailLevel, posX, posZ))
|
||||
{
|
||||
dataPoint = lodDim.getData(detailLevel, posX, posZ);
|
||||
if(DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH)
|
||||
if (DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH)
|
||||
continue;
|
||||
adjData = new long[NUMBER_OF_DIRECTION];
|
||||
for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++)
|
||||
{
|
||||
xAdj = posX + ADJ_DIRECTION[direction][0];
|
||||
zAdj = posZ + ADJ_DIRECTION[direction][1];
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.x;
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel,zAdj) - playerChunkPos.z;
|
||||
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.x;
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.z;
|
||||
|
||||
if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist))
|
||||
{
|
||||
if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
|
||||
&& posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
&& posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
{
|
||||
adjData[direction]= lodDim.getData(detailLevel, xAdj, zAdj);
|
||||
adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj);
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
{
|
||||
@@ -297,22 +301,23 @@ public class LodBufferBuilder
|
||||
}
|
||||
}
|
||||
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData,
|
||||
detailLevel, posX, posZ, boxCache[xR][zR],renderer.previousDebugMode);
|
||||
detailLevel, posX, posZ, boxCache[xR][zR], renderer.previousDebugMode);
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}// for pos to in list to render
|
||||
// the thread executed successfully
|
||||
|
||||
} // for pos to in list to render
|
||||
// the thread executed successfully
|
||||
return true;
|
||||
};
|
||||
nodeToRenderThreads.add(dataToRenderThread);
|
||||
}
|
||||
}// region z
|
||||
}// region z
|
||||
} // region z
|
||||
} // region z
|
||||
long renderStart = System.currentTimeMillis();
|
||||
// wait for all threads to finish
|
||||
List<Future<Boolean>> futuresBuffer = bufferBuilderThreads.invokeAll(nodeToRenderThreads);
|
||||
@@ -327,8 +332,7 @@ public class LodBufferBuilder
|
||||
}
|
||||
}
|
||||
long renderEnd = System.currentTimeMillis();
|
||||
|
||||
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
@SuppressWarnings("unused")
|
||||
long buildTime = endTime - startTime;
|
||||
@@ -343,37 +347,38 @@ public class LodBufferBuilder
|
||||
|
||||
// mark that the buildable buffers as ready to swap
|
||||
switchVbos = true;
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: ");
|
||||
e.printStackTrace();
|
||||
} finally
|
||||
}
|
||||
finally
|
||||
{
|
||||
// regardless of if we successfully created the buffers
|
||||
// we are done generating.
|
||||
generatingBuffers = false;
|
||||
|
||||
|
||||
// clean up any potentially open resources
|
||||
if (buildableBuffers != null)
|
||||
closeBuffers(fullRegen, lodDim);
|
||||
|
||||
|
||||
// upload the new buffers
|
||||
uploadBuffers(fullRegen, lodDim);
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
mainGenThread.execute(thread);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//===============================//
|
||||
// BufferBuilder related methods //
|
||||
//===============================//
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called from the LodRenderer to create the
|
||||
* BufferBuilders. <br><br>
|
||||
@@ -383,29 +388,41 @@ public class LodBufferBuilder
|
||||
public void setupBuffers(int numbRegionsWide, int bufferMaxCapacity)
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
|
||||
previousRegionWidth = numbRegionsWide;
|
||||
previousBufferSize = bufferMaxCapacity;
|
||||
|
||||
|
||||
|
||||
buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide];
|
||||
|
||||
|
||||
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide];
|
||||
drawableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide];
|
||||
|
||||
|
||||
clearByteBuffer = new BufferBuilder(bufferMaxCapacity).buffer;
|
||||
clearByteBuffer.position(clearByteBuffer.limit()-1);
|
||||
|
||||
for (int x = 0; x < numbRegionsWide; x++)
|
||||
{
|
||||
for (int z = 0; z < numbRegionsWide; z++)
|
||||
{
|
||||
buildableBuffers[x][z] = new BufferBuilder(bufferMaxCapacity);
|
||||
|
||||
|
||||
buildableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
|
||||
drawableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT);
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableVbos[x][z].id);
|
||||
GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, bufferMaxCapacity, GL15C.GL_DYNAMIC_DRAW);
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableVbos[x][z].id);
|
||||
GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, bufferMaxCapacity, GL15C.GL_DYNAMIC_DRAW);
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sets the buffers and Vbos to null, forcing them to be recreated. <br><br>
|
||||
* <p>
|
||||
@@ -414,15 +431,14 @@ public class LodBufferBuilder
|
||||
public void destroyBuffers()
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
|
||||
buildableBuffers = null;
|
||||
buildableVbos = null;
|
||||
drawableVbos = null;
|
||||
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calls begin on each of the buildable BufferBuilders.
|
||||
*/
|
||||
@@ -437,7 +453,7 @@ public class LodBufferBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls end on each of the buildable BufferBuilders.
|
||||
*/
|
||||
@@ -445,34 +461,88 @@ public class LodBufferBuilder
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
|
||||
|
||||
if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building() && (fullRegen || lodDim.regen[x][z]))
|
||||
{
|
||||
buildableBuffers[x][z].end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called from the LodRenderer to create the
|
||||
* BufferBuilders at the right size.
|
||||
*/
|
||||
private void uploadBuffers(boolean fullRegen, LodDimension lodDim)
|
||||
{
|
||||
GlProxy.getInstance().setGlContext(buildingContext);
|
||||
|
||||
for (int x = 0; x < buildableVbos.length; x++)
|
||||
{
|
||||
for (int z = 0; z < buildableVbos.length; z++)
|
||||
{
|
||||
if (fullRegen || lodDim.regen[x][z])
|
||||
{
|
||||
buildableVbos[x][z].upload(buildableBuffers[x][z]);
|
||||
// if (fullRegen || lodDim.regen[x][z])
|
||||
// {
|
||||
vboUpload(x, z, lodDim, buildableVbos);
|
||||
lodDim.regen[x][z] = false;
|
||||
}
|
||||
}
|
||||
// }// regen region
|
||||
}// z
|
||||
}// x
|
||||
|
||||
GL11.glFlush();
|
||||
GlProxy.getInstance().setGlContext(GlProxyContext.NONE);
|
||||
}
|
||||
|
||||
public void vboUpload(int xLocal, int zLocal, LodDimension lodDim, VertexBuffer[][] buildableVbos)
|
||||
{
|
||||
VertexBuffer vbo = buildableVbos[xLocal][zLocal];
|
||||
BufferBuilder bufferBuilder = buildableBuffers[xLocal][zLocal];
|
||||
GlProxyContext test = GlProxy.getInstance().getGlContext();
|
||||
|
||||
long start = System.nanoTime();
|
||||
long end = start;
|
||||
|
||||
if (vbo.id != -1)
|
||||
{
|
||||
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
|
||||
|
||||
ByteBuffer bytebuffer = pair.getSecond();
|
||||
vbo.vertexCount = bytebuffer.remaining() / vbo.format.getVertexSize();
|
||||
|
||||
if (xLocal == 0 && zLocal == 0) while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id); // 34962 = 0x8892 = GL_ARRAY_BUFFER
|
||||
// ByteBuffer vboBuffer = GL15C.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
||||
|
||||
GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, bytebuffer, GL15C.GL_STATIC_DRAW);
|
||||
|
||||
// clearByteBuffer.position(0);
|
||||
// clearByteBuffer.position(clearByteBuffer.limit()-1);
|
||||
//clearByteBuffer
|
||||
|
||||
// GL15C.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0L, clearByteBuffer);
|
||||
GL15C.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0L, bytebuffer);
|
||||
|
||||
|
||||
// long bufferSize = GL43C.glGetBufferParameteri64(GL15.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE);
|
||||
// GL43C.glClearBufferSubData(GL15.GL_ARRAY_BUFFER, GL43., 0, bufferSize, GL11.GL_RGB, GL11.GL_FLOAT, (ByteBuffer) null);
|
||||
// if (xLocal == 0 && zLocal == 0) ClientProxy.LOGGER.info("err: " + GL11.glGetError());
|
||||
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
// GL15C.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
end = System.nanoTime();
|
||||
|
||||
|
||||
|
||||
if (xLocal == 0 && zLocal == 0)
|
||||
{
|
||||
double time = (end - start) * 0.000001 * lodDim.getWidth() * lodDim.getWidth();
|
||||
ClientProxy.LOGGER.info("upload: " + time + "\t" + test);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the newly created VBOs
|
||||
*/
|
||||
@@ -485,16 +555,24 @@ public class LodBufferBuilder
|
||||
VertexBuffer[][] tmp = drawableVbos;
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmp;
|
||||
|
||||
|
||||
GlProxyContext context = renderContext;
|
||||
renderContext = buildingContext;
|
||||
buildingContext = context;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
bufferLock.unlock();
|
||||
|
||||
// ClientProxy.LOGGER.info("Get vertex Buffers: " + GlProxy.getInstance().getGlContext());
|
||||
}
|
||||
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos);
|
||||
|
||||
// ClientProxy.LOGGER.info("Get vbo first: " + drawableVbos[0][0].id + "\t" + GlProxy.getInstance().getGlContext());
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos, renderContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple container to pass multiple objects back in the getVertexBuffers method.
|
||||
*/
|
||||
@@ -502,14 +580,16 @@ public class LodBufferBuilder
|
||||
{
|
||||
public VertexBuffer[][] vbos;
|
||||
public ChunkPos drawableCenterChunkPos;
|
||||
|
||||
public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos)
|
||||
public GlProxyContext drawingContext;
|
||||
|
||||
public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos, GlProxyContext newDrawingContext)
|
||||
{
|
||||
vbos = newVbos;
|
||||
drawableCenterChunkPos = newDrawableCenterChunkPos;
|
||||
drawingContext = newDrawingContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If this is true the buildable near and far
|
||||
* buffers have been generated and are ready to be
|
||||
@@ -519,6 +599,5 @@ public class LodBufferBuilder
|
||||
{
|
||||
return switchVbos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -117,8 +117,8 @@ public class LodBuilder
|
||||
playerPosZ = chunk.getPos().getMinBlockZ();
|
||||
} else
|
||||
{
|
||||
playerPosX = (int) world.players().get(0).getX();
|
||||
playerPosZ = (int) world.players().get(0).getZ();
|
||||
playerPosX = (int) MinecraftWrapper.INSTANCE.getPlayer().getX();
|
||||
playerPosZ = (int) MinecraftWrapper.INSTANCE.getPlayer().getZ();
|
||||
}
|
||||
if (lodWorld.getLodDimension(dim) == null)
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
// it uses doubles to specify its location, unlike the model view matrix
|
||||
// which only uses floats
|
||||
double x = -bufferCenterBlockPos.getX();
|
||||
double z = -bufferCenterBlockPos.getZ();;
|
||||
double z = -bufferCenterBlockPos.getZ();
|
||||
box.set(width, height - depth, width);
|
||||
box.move((int) (xOffset + x), (int) (yOffset + depth), (int) (zOffset + z));
|
||||
}
|
||||
|
||||
@@ -99,6 +99,8 @@ public class ClientProxy
|
||||
*/
|
||||
public void renderLods(float partialTicks)
|
||||
{
|
||||
GlProxy.getInstance();
|
||||
|
||||
DetailDistanceUtil.updateSettings();
|
||||
if (mc == null || mc.getPlayer() == null || !lodWorld.getIsWorldLoaded())
|
||||
return;
|
||||
@@ -119,7 +121,7 @@ public class ClientProxy
|
||||
|
||||
|
||||
// comment out when creating a release
|
||||
//applyConfigOverrides();
|
||||
applyConfigOverrides();
|
||||
|
||||
|
||||
// Note to self:
|
||||
@@ -129,6 +131,7 @@ public class ClientProxy
|
||||
IProfiler profiler = mc.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("LOD");
|
||||
|
||||
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
|
||||
|
||||
profiler.pop(); // end LOD
|
||||
@@ -164,14 +167,14 @@ public class ClientProxy
|
||||
// LodConfig.CLIENT.graphics.saturationMultiplier.set(1.0);
|
||||
|
||||
// LodConfig.CLIENT.worldGenerator.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
// LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(256);
|
||||
LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(256);
|
||||
// LodConfig.CLIENT.worldGenerator.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
|
||||
// LodConfig.CLIENT.graphics.lodQuality.set(3);
|
||||
LodConfig.CLIENT.graphics.lodQuality.set(3);
|
||||
// LodConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(false);
|
||||
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.set(2000); // 2000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.set(1000); // 1000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.set(50); // 5000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.set(2000); // 2000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.set(1000); // 1000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.set(5000); // 5000
|
||||
|
||||
LodConfig.CLIENT.debugging.enableDebugKeybinding.set(true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
package com.seibel.lod.proxy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.opengl.WGL;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.builders.LodBufferBuilder;
|
||||
|
||||
/**
|
||||
* A singleton that holds references to different openGL contexts.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-9-2021
|
||||
*/
|
||||
public class GlProxy
|
||||
{
|
||||
private static GlProxy instance = null;
|
||||
|
||||
public final long deviceContext;
|
||||
|
||||
public long minecraftGlContext;
|
||||
public GLCapabilities minecraftGlCapabilities;
|
||||
|
||||
public long lodBuilderGlContext;
|
||||
public GLCapabilities lodBuilderGlCapabilities;
|
||||
public long lodRenderGlContext;
|
||||
public GLCapabilities lodRenderGlCapabilities;
|
||||
|
||||
private GlProxy()
|
||||
{
|
||||
GLFWErrorCallback errorfun = GLFWErrorCallback.createPrint();
|
||||
GLFW.glfwSetErrorCallback(errorfun);
|
||||
|
||||
|
||||
// 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!");
|
||||
|
||||
minecraftGlContext = WGL.wglGetCurrentContext();
|
||||
minecraftGlCapabilities = GL.getCapabilities();
|
||||
deviceContext = WGL.wglGetCurrentDC();
|
||||
|
||||
|
||||
Callable<Void> callable = () ->
|
||||
{
|
||||
lodBuilderGlContext = WGL.wglCreateContext(deviceContext);
|
||||
// if (!WGL.wglShareLists(minecraftGlContext, lodBuilderGlContext))
|
||||
// throw new IllegalStateException("Unable to share lists between Minecraft and builder contexts.");
|
||||
if (!WGL.wglMakeCurrent(deviceContext, lodBuilderGlContext))
|
||||
throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.BUILDER.toString() + "] from [" + GlProxyContext.MINECRAFT.toString() + "]");
|
||||
lodBuilderGlCapabilities = GL.createCapabilities();
|
||||
WGL.wglMakeCurrent(deviceContext, 0L);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
ArrayList<Callable<Void>> list = new ArrayList<Callable<Void>>();
|
||||
list.add(callable);
|
||||
try
|
||||
{
|
||||
List<Future<Void>> futuresBuffer = LodBufferBuilder.mainGenThread.invokeAll(list);
|
||||
|
||||
for (Future<Void> future : futuresBuffer)
|
||||
if (!future.isDone())
|
||||
ClientProxy.LOGGER.error("GLProxy failed to setup.");
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
lodRenderGlContext = WGL.wglCreateContext(deviceContext);
|
||||
// if (!WGL.wglShareLists(lodBuilderGlContext, lodRenderGlContext))
|
||||
// throw new IllegalStateException("Unable to share lists between builder and render contexts.");
|
||||
if (!WGL.wglMakeCurrent(deviceContext, lodRenderGlContext))
|
||||
throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.BUILDER.toString() + "] from [" + GlProxyContext.RENDER.toString() + "]");
|
||||
lodRenderGlCapabilities = GL.createCapabilities();
|
||||
WGL.wglMakeCurrent(deviceContext, minecraftGlContext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A simple wrapper function to make switching contexts easier
|
||||
*/
|
||||
public void setGlContext(GlProxyContext context)
|
||||
{
|
||||
GlProxyContext currentContext = getGlContext();
|
||||
|
||||
long contextPointer = 0L;
|
||||
GLCapabilities newGlCapabilities = null;
|
||||
switch(context)
|
||||
{
|
||||
case BUILDER:
|
||||
contextPointer = lodBuilderGlContext;
|
||||
newGlCapabilities = lodBuilderGlCapabilities;
|
||||
break;
|
||||
case RENDER:
|
||||
contextPointer = lodRenderGlContext;
|
||||
newGlCapabilities = lodRenderGlCapabilities;
|
||||
break;
|
||||
case MINECRAFT:
|
||||
contextPointer = minecraftGlContext;
|
||||
newGlCapabilities = minecraftGlCapabilities;
|
||||
break;
|
||||
case NONE:
|
||||
contextPointer = 0L; // equivalent to null
|
||||
newGlCapabilities = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
// should never happen, here to make the compiler happy
|
||||
}
|
||||
|
||||
if (!WGL.wglMakeCurrent(deviceContext, contextPointer))
|
||||
throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + context.toString() + "] from [" + currentContext.toString() + "]");
|
||||
|
||||
GL.setCapabilities(newGlCapabilities);
|
||||
}
|
||||
public GlProxyContext getGlContext()
|
||||
{
|
||||
long currentContext = WGL.wglGetCurrentContext();
|
||||
if(currentContext == lodBuilderGlContext)
|
||||
{
|
||||
return GlProxyContext.BUILDER;
|
||||
}
|
||||
else if(currentContext == lodRenderGlContext)
|
||||
{
|
||||
return GlProxyContext.RENDER;
|
||||
}
|
||||
else if(currentContext == minecraftGlContext)
|
||||
{
|
||||
return GlProxyContext.MINECRAFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GlProxyContext.NONE;
|
||||
}
|
||||
}
|
||||
/** Minecraft, Alpha, Beta, None */
|
||||
public enum GlProxyContext
|
||||
{
|
||||
MINECRAFT,
|
||||
BUILDER,
|
||||
RENDER,
|
||||
|
||||
/** used to un-bind threads */
|
||||
NONE,
|
||||
}
|
||||
|
||||
public static GlProxy getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new GlProxy();
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,10 @@ import java.util.Iterator;
|
||||
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL15C;
|
||||
import org.lwjgl.opengl.NVFogDistance;
|
||||
import org.lwjgl.opengl.WGL;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
@@ -43,6 +46,8 @@ import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.NearFarFogSettings;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.proxy.GlProxy;
|
||||
import com.seibel.lod.proxy.GlProxy.GlProxyContext;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
@@ -97,7 +102,8 @@ public class LodRenderer
|
||||
* Does this computer's GPU support fancy fog?
|
||||
*/
|
||||
private static Boolean fancyFogAvailable = null;
|
||||
|
||||
private static GlProxy glProxy;
|
||||
private GlProxyContext renderContext = null;
|
||||
|
||||
/**
|
||||
* If true the LODs colors will be replaced with
|
||||
@@ -191,6 +197,7 @@ public class LodRenderer
|
||||
// only check the GPU capability's once
|
||||
if (fancyFogAvailable == null)
|
||||
{
|
||||
//TODO add this to the GlProxy
|
||||
// see if this GPU can run fancy fog
|
||||
fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
|
||||
|
||||
@@ -198,6 +205,10 @@ public class LodRenderer
|
||||
{
|
||||
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
|
||||
}
|
||||
|
||||
// create the GlProxy TODO this should probably be done somewhere else
|
||||
glProxy = GlProxy.getInstance();
|
||||
ClientProxy.LOGGER.error("share lists renderer: " + WGL.wglShareLists(GlProxy.getInstance().minecraftGlContext, GlProxy.getInstance().lodBuilderGlContext));
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +239,21 @@ public class LodRenderer
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
// ...ending here
|
||||
|
||||
if (lodBufferBuilder.newBuffersAvaliable())
|
||||
{
|
||||
// this has to be called after the VBOs have been drawn
|
||||
// otherwise rubber banding may occur
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
if (renderContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GlProxy.getInstance().setGlContext(renderContext);
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
@@ -236,7 +261,9 @@ public class LodRenderer
|
||||
//===========================//
|
||||
|
||||
// set the required open GL settings
|
||||
|
||||
|
||||
GlProxy.getInstance().setGlContext(renderContext);
|
||||
|
||||
if (LodConfig.CLIENT.debugging.debugMode.get() == DebugMode.SHOW_DETAIL_WIREFRAME)
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
|
||||
else
|
||||
@@ -278,15 +305,14 @@ public class LodRenderer
|
||||
// rendering //
|
||||
//===========//
|
||||
profiler.popPush("LOD draw");
|
||||
|
||||
|
||||
if (vbos != null)
|
||||
{
|
||||
Entity cameraEntity = mc.getCameraEntity();
|
||||
Vector3d cameraDir = cameraEntity.getLookAngle().normalize();
|
||||
cameraDir = mc.getOptions().getCameraType().isMirrored() ? cameraDir.reverse() : cameraDir;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// used to determine what type of fog to render
|
||||
int halfWidth = vbos.length / 2;
|
||||
int quarterWidth = vbos.length / 4;
|
||||
@@ -309,7 +335,7 @@ public class LodRenderer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// cleanup //
|
||||
@@ -338,18 +364,18 @@ public class LodRenderer
|
||||
// clear the depth buffer so anything drawn is drawn
|
||||
// over the LODs
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
|
||||
GlProxy.getInstance().setGlContext(GlProxyContext.MINECRAFT);
|
||||
|
||||
// replace the buffers used to draw and build,
|
||||
// this is only done when the createLodBufferGenerationThread
|
||||
// has finished executing on a parallel thread.
|
||||
if (lodBufferBuilder.newBuffersAvaliable())
|
||||
{
|
||||
// this has to be called after the VBOs have been drawn
|
||||
// otherwise rubber banding may occur
|
||||
swapBuffers();
|
||||
}
|
||||
// if (lodBufferBuilder.newBuffersAvaliable())
|
||||
// {
|
||||
// // this has to be called after the VBOs have been drawn
|
||||
// // otherwise rubber banding may occur
|
||||
// swapBuffers();
|
||||
// }
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
@@ -365,13 +391,13 @@ public class LodRenderer
|
||||
if (vbo == null)
|
||||
return;
|
||||
|
||||
vbo.bind();
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
|
||||
// 0L is the starting pointer
|
||||
LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
|
||||
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
|
||||
|
||||
VertexBuffer.unbind();
|
||||
|
||||
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
LOD_VERTEX_FORMAT.clearBufferState();
|
||||
}
|
||||
|
||||
@@ -665,6 +691,7 @@ public class LodRenderer
|
||||
VertexBuffersAndOffset result = lodBufferBuilder.getVertexBuffers();
|
||||
vbos = result.vbos;
|
||||
vbosCenter = result.drawableCenterChunkPos;
|
||||
renderContext = result.drawingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,10 @@ public net.minecraft.world.lighting.WorldLightManager field_215576_a # blockEngi
|
||||
public net.minecraft.world.lighting.WorldLightManager field_215577_b # skyEngine
|
||||
public net.minecraft.world.gen.feature.Feature field_236290_a_ # configuredCodec
|
||||
|
||||
# used for uploading vertex buffers off the render thread
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177365_a # id
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177363_b # format
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177364_c # vertexCount
|
||||
|
||||
|
||||
#=====================#
|
||||
|
||||
Reference in New Issue
Block a user