From 6d776407a40ef664defc92ff8b369fce506ad938 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 15 Aug 2021 14:52:17 -0500 Subject: [PATCH] Optimize the BufferBuilder --- .../lod/builders/LodNodeBufferBuilder.java | 460 ++++++++++-------- .../{NearFarBuffer.java => NearFarVbos.java} | 20 +- .../seibel/lod/render/LodNodeRenderer.java | 45 +- 3 files changed, 269 insertions(+), 256 deletions(-) rename src/main/java/com/seibel/lod/objects/{NearFarBuffer.java => NearFarVbos.java} (73%) diff --git a/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java index 49be8a5b7..a773cd730 100644 --- a/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java @@ -29,12 +29,14 @@ import com.seibel.lod.enums.LodDetail; import com.seibel.lod.handlers.LodConfig; import com.seibel.lod.objects.LodQuadTreeDimension; import com.seibel.lod.objects.LodQuadTreeNode; -import com.seibel.lod.objects.NearFarBuffer; +import com.seibel.lod.objects.NearFarVbos; +import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.render.LodNodeRenderer; import com.seibel.lod.util.LodUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.vertex.VertexBuffer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.server.ServerWorld; @@ -44,7 +46,7 @@ import net.minecraftforge.common.WorldWorkerManager; * This object is used to create NearFarBuffer objects. * * @author James Seibel - * @version 8-14-2021 + * @version 8-15-2021 */ public class LodNodeBufferBuilder { @@ -56,22 +58,32 @@ public class LodNodeBufferBuilder private LodNodeBuilder LodQuadTreeNodeBuilder; /** The buffers that are used to create LODs using near fog */ - public volatile BufferBuilder buildableNearBuffer; + public BufferBuilder buildableNearBuffer; /** The buffers that are used to create LODs using far fog */ - public volatile BufferBuilder buildableFarBuffer; + public BufferBuilder buildableFarBuffer; + + /** Used when building a new VBO */ + public VertexBuffer buildableNearVbo; + /** Used when building a new VBO */ + public VertexBuffer buildableFarVbo; + + /** VBO that is sent over to the LodNodeRenderer */ + public VertexBuffer drawableNearVbo; + /** VBO that is sent over to the LodNodeRenderer */ + public VertexBuffer drawableFarVbo; /** if this is true the LOD buffers are currently being * regenerated. */ - public volatile boolean generatingBuffers = false; + 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 volatile boolean switchBuffers = false; + private boolean switchVbos = false; /** This keeps track of how many chunk generation requests are on going. * This is to prevent chunks from being generated for a long time in an area * the player is no longer in. */ - public volatile AtomicInteger numberOfChunksWaitingToGenerate = new AtomicInteger(0); + public AtomicInteger numberOfChunksWaitingToGenerate = new AtomicInteger(0); @@ -110,8 +122,8 @@ public class LodNodeBufferBuilder if (generatingBuffers) return; - if (buildableNearBuffer == null || buildableFarBuffer == null) - throw new IllegalStateException("generateLodBuffersAsync was called before the buildableNearBuffer and buildableFarBuffer were created."); + if (buildableNearBuffer == null) + throw new IllegalStateException("\"generateLodBuffersAsync\" was called before the \"setupBuffers\" method was called."); if (previousDimension != lodDim) { @@ -125,223 +137,241 @@ public class LodNodeBufferBuilder // round the player's block position down to the nearest chunk BlockPos ChunkPos playerChunkPos = new ChunkPos(playerBlockPos); - playerBlockPos = playerChunkPos.getWorldPosition(); + BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition(); // this is where we will start drawing squares // (exactly half the total width) - BlockPos startBlockPos = new BlockPos(-(numbChunksWide * 16 / 2) + playerBlockPos.getX(), 0, -(numbChunksWide * 16 / 2) + playerBlockPos.getZ()); + BlockPos startBlockPos = new BlockPos(-(numbChunksWide * 16 / 2) + playerBlockPosRounded.getX(), 0, -(numbChunksWide * 16 / 2) + playerBlockPosRounded.getZ()); ChunkPos startChunkPos = new ChunkPos(startBlockPos); Thread thread = new Thread(() -> { - // index of the chunk currently being added to the - // generation list - int chunkGenIndex = 0; - - ChunkPos[] chunksToGen = new ChunkPos[maxChunkGenRequests]; - // if we don't have a full number of chunks to generate in chunksToGen - // we can top it off from the reserve - ChunkPos[] chunksToGenReserve = new ChunkPos[maxChunkGenRequests]; - - // Used when determining what detail level to use at what distance - int maxBlockDistance = (numbChunksWide / 2) * 16; - - // generate our new buildable buffers - buildableNearBuffer.begin(GL11.GL_QUADS, LodNodeRenderer.LOD_VERTEX_FORMAT); - buildableFarBuffer.begin(GL11.GL_QUADS, LodNodeRenderer.LOD_VERTEX_FORMAT); - - // used when determining which chunks are closer when queuing distance generation - int minChunkDist = Integer.MAX_VALUE; - - // x axis - for (int i = 0; i < numbChunksWide; i++) + try { - // z axis - for (int j = 0; j < numbChunksWide; j++) { - int chunkX = i + startChunkPos.x; - int chunkZ = j + startChunkPos.z; - - // skip any chunks that Minecraft is going to render - if (isCoordInCenterArea(i, j, (numbChunksWide / 2)) - && renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ))) + + long startTime = System.currentTimeMillis(); + + // index of the chunk currently being added to the + // generation list + int chunkGenIndex = 0; + + ChunkPos[] chunksToGen = new ChunkPos[maxChunkGenRequests]; + // if we don't have a full number of chunks to generate in chunksToGen + // we can top it off from the reserve + ChunkPos[] chunksToGenReserve = new ChunkPos[maxChunkGenRequests]; + + // Used when determining what detail level to use at what distance + int maxBlockDistance = (numbChunksWide / 2) * 16; + + // generate our new buildable buffers + buildableNearBuffer.begin(GL11.GL_QUADS, LodNodeRenderer.LOD_VERTEX_FORMAT); + buildableFarBuffer.begin(GL11.GL_QUADS, LodNodeRenderer.LOD_VERTEX_FORMAT); + + // used when determining which chunks are closer when queuing distance + // generation + int minChunkDist = Integer.MAX_VALUE; + + // x axis + for (int i = 0; i < numbChunksWide; i++) + { + // z axis + for (int j = 0; j < numbChunksWide; j++) { - continue; - } - - - // set where this square will be drawn in the world - double xOffset = (LodUtil.CHUNK_WIDTH * i) + // offset by the number of LOD blocks - startBlockPos.getX(); // offset so the center LOD block is centered underneath the player - double yOffset = 0; - double zOffset = (LodUtil.CHUNK_WIDTH * j) + startBlockPos.getZ(); - - LodQuadTreeNode lod = lodDim.getLodFromCoordinates(new ChunkPos(chunkX, chunkZ), LodUtil.CHUNK_DETAIL_LEVEL); - - if (lod == null || lod.complexity == DistanceGenerationMode.NONE) { - // generate a new chunk if no chunk currently exists - // and we aren't waiting on any other chunks to generate - if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) { - ChunkPos pos = new ChunkPos(chunkX, chunkZ); - - // alternate determining logic that - // can be used for debugging -// if (chunksToGen == null) -// { -// chunkGenIndex = 0; -// chunksToGen = new ChunkPos[maxChunkGenRequests]; -// } -// -// if (chunkGenIndex < maxChunkGenRequests) -// { -// chunksToGen[chunkGenIndex] = pos; -// chunkGenIndex++; -// } - - - // determine if this position is closer to the player - // than the previous - int newDistance = playerChunkPos.getChessboardDistance(pos); - - // issue #40 - // TODO optimize this code, - // using the purely optimized code above we can achieve close to - // 100% CPU utilization, this code generally achieves 40 - 50% - // after a certain point; and I'm sure there is a better data - // structure for this. - if (newDistance < minChunkDist) { - // this chunk is closer, clear any previous - // positions and update the new minimum distance - minChunkDist = newDistance; + int chunkX = i + startChunkPos.x; + int chunkZ = j + startChunkPos.z; + + // skip any chunks that Minecraft is going to render + if (isCoordInCenterArea(i, j, (numbChunksWide / 2)) + && renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ))) + { + continue; + } + + // set where this square will be drawn in the world + double xOffset = (LodUtil.CHUNK_WIDTH * i) + // offset by the number of LOD blocks + startBlockPos.getX(); // offset so the center LOD block is centered underneath the player + double yOffset = 0; + double zOffset = (LodUtil.CHUNK_WIDTH * j) + startBlockPos.getZ(); + + LodQuadTreeNode lod = lodDim.getLodFromCoordinates(new ChunkPos(chunkX, chunkZ), LodUtil.CHUNK_DETAIL_LEVEL); + + if (lod == null || lod.complexity == DistanceGenerationMode.NONE) + { + // generate a new chunk if no chunk currently exists + // and we aren't waiting on any other chunks to generate + if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) + { + ChunkPos pos = new ChunkPos(chunkX, chunkZ); - // move all the old chunks into the reserve - ChunkPos[] newReserve = new ChunkPos[maxChunkGenRequests]; - int oldToGenIndex = 0; - int oldReserveIndex = 0; - for (int tmpIndex = 0; tmpIndex < newReserve.length; tmpIndex++) { - // we don't check if the boundaries are good since - // the tmp array will always be the same length - // as chunksToGen and chunksToGenReserve + // alternate determining logic that + // can be used for debugging +// if (chunksToGen == null) +// { +// chunkGenIndex = 0; +// chunksToGen = new ChunkPos[maxChunkGenRequests]; +// } +// +// if (chunkGenIndex < maxChunkGenRequests) +// { +// chunksToGen[chunkGenIndex] = pos; +// chunkGenIndex++; +// } + + // determine if this position is closer to the player + // than the previous + int newDistance = playerChunkPos.getChessboardDistance(pos); + + // issue #40 + // TODO optimize this code, + // using the purely optimized code above we can achieve close to + // 100% CPU utilization, this code generally achieves 40 - 50% + // after a certain point; and I'm sure there is a better data + // structure for this. + if (newDistance < minChunkDist) + { + // this chunk is closer, clear any previous + // positions and update the new minimum distance + minChunkDist = newDistance; - if (chunksToGen[oldToGenIndex] != null) { - // add all the closest chunks... - newReserve[tmpIndex] = chunksToGen[oldToGenIndex]; - oldToGenIndex++; - } else if (chunksToGenReserve[oldReserveIndex] != null) { - // ...then add all the previous reserve chunks - // (which are farther away) - newReserve[tmpIndex] = chunksToGenReserve[oldToGenIndex]; - oldReserveIndex++; - } else { - // we have moved all the items from - // the old chunksToGen and reserve - break; + // move all the old chunks into the reserve + ChunkPos[] newReserve = new ChunkPos[maxChunkGenRequests]; + int oldToGenIndex = 0; + int oldReserveIndex = 0; + for (int tmpIndex = 0; tmpIndex < newReserve.length; tmpIndex++) + { + // we don't check if the boundaries are good since + // the tmp array will always be the same length + // as chunksToGen and chunksToGenReserve + + if (chunksToGen[oldToGenIndex] != null) + { + // add all the closest chunks... + newReserve[tmpIndex] = chunksToGen[oldToGenIndex]; + oldToGenIndex++; + } + else if (chunksToGenReserve[oldReserveIndex] != null) + { + // ...then add all the previous reserve chunks + // (which are farther away) + newReserve[tmpIndex] = chunksToGenReserve[oldToGenIndex]; + oldReserveIndex++; + } + else + { + // we have moved all the items from + // the old chunksToGen and reserve + break; + } } - } - chunksToGenReserve = newReserve; - - - chunkGenIndex = 0; - chunksToGen = new ChunkPos[maxChunkGenRequests]; - chunksToGen[chunkGenIndex] = pos; - chunkGenIndex++; - } else if (newDistance <= minChunkDist) { - // this chunk position is as close or closers than the - // minimum distance - if (chunkGenIndex < maxChunkGenRequests) { - // we are still under the number of chunks to generate - // add this position to the list + chunksToGenReserve = newReserve; + + chunkGenIndex = 0; + chunksToGen = new ChunkPos[maxChunkGenRequests]; chunksToGen[chunkGenIndex] = pos; chunkGenIndex++; } - } + else if (newDistance <= minChunkDist) + { + // this chunk position is as close or closers than the + // minimum distance + if (chunkGenIndex < maxChunkGenRequests) + { + // we are still under the number of chunks to generate + // add this position to the list + chunksToGen[chunkGenIndex] = pos; + chunkGenIndex++; + } + } + + } // lod null and can generate more chunks - } // lod null and can generate more chunks + // don't render this null/empty chunk + continue; + + } // lod null or empty - // don't render this null/empty chunk - continue; + // should we draw near or far fog? + BufferBuilder currentBuffer = null; + if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2)) + currentBuffer = buildableNearBuffer; + else + currentBuffer = buildableFarBuffer; - } // lod null or empty + // determine detail level should this LOD be drawn at + int distance = (int) Math.sqrt(Math.pow((playerBlockPosRounded.getX() - lod.getCenter().getX()), 2) + Math.pow((playerBlockPosRounded.getZ() - lod.getCenter().getZ()), 2)); + LodDetail detail = LodDetail.getDetailForDistance(LodConfig.CLIENT.maxDrawDetail.get(), distance, maxBlockDistance); + + // get the desired LodTemplate and + // add this LOD to the buffer + LodConfig.CLIENT.lodTemplate.get().template.addLodToBuffer(currentBuffer, lodDim, lod, + xOffset, yOffset, zOffset, renderer.debugging, detail); + } + } + + // issue #19 + // TODO add a way for a server side mod to generate chunks requested here + if (mc.hasSingleplayerServer()) + { + ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); - - // should we draw near or far fog? - BufferBuilder currentBuffer = null; - if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2)) - currentBuffer = buildableNearBuffer; - else - currentBuffer = buildableFarBuffer; - - - // determine detail level should this LOD be drawn at - int distance = (int) Math.sqrt(Math.pow((mc.player.getX() - lod.getCenter().getX()),2) + Math.pow((mc.player.getZ() - lod.getCenter().getZ()),2)); - LodDetail detail = LodDetail.getDetailForDistance(LodConfig.CLIENT.maxDrawDetail.get(), distance, maxBlockDistance); - - - // get the desired LodTemplate and - // add this LOD to the buffer - LodConfig.CLIENT.lodTemplate.get(). - template.addLodToBuffer(currentBuffer, lodDim, lod, - xOffset , yOffset, zOffset, renderer.debugging, detail); - /* - LodDetail detail = LodConfig.CLIENT.lodDetail.get(); - for(int x = 0; x < detail.dataPointLengthCount; x++){ - for(int z = 0; z < detail.dataPointLengthCount; z++) { - int posX = LodUtil.convertLevelPos(lod.startBlockPos.getX() + (x*detail.dataPointWidth), 0, detail.detailLevel); - int posZ = LodUtil.convertLevelPos(lod.startBlockPos.getZ() + (z*detail.dataPointWidth), 0, detail.detailLevel); - LodQuadTreeNode newLod = lodDim.getLodFromCoordinates(posX, posZ, detail.detailLevel); - System.out.print("printing "); - System.out.println(newLod); - if(newLod != null) { - LodConfig.CLIENT.lodTemplate.get(). - template.addLodToBuffer(currentBuffer, lodDim, newLod, - xOffset + (x*detail.dataPointWidth), yOffset, zOffset + (z*detail.dataPointWidth), renderer.debugging); - } + // make sure we have as many chunks to generate as we are allowed + if (chunkGenIndex < maxChunkGenRequests) + { + for (int i = chunkGenIndex, j = 0; i < maxChunkGenRequests; i++, j++) + { + chunksToGen[i] = chunksToGenReserve[j]; } } - */ - } - } - - - // issue #19 - // TODO add a way for a server side mod to generate chunks requested here - if(mc.hasSingleplayerServer()) - { - ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); - - // make sure we have as many chunks to generate as we are allowed - if (chunkGenIndex < maxChunkGenRequests) - { - for(int i = chunkGenIndex, j = 0; i < maxChunkGenRequests; i++, j++) + + // start chunk generation + for (ChunkPos chunkPos : chunksToGen) { - chunksToGen[i] = chunksToGenReserve[j]; + // don't add null chunkPos (which shouldn't happen anyway) + // or add more to the generation queue + if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) + break; + + // TODO add a list of locations we are waiting to generate so we don't add the + // same position to the queue multiple times + + numberOfChunksWaitingToGenerate.addAndGet(1); + + LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, renderer, LodQuadTreeNodeBuilder, this, lodDim, serverWorld); + WorldWorkerManager.addWorker(genWorker); } } - // start chunk generation - for(ChunkPos chunkPos : chunksToGen) + // finish the buffer building + buildableNearBuffer.end(); + buildableFarBuffer.end(); + + // upload the new buffers + buildableNearVbo.upload(buildableNearBuffer); + buildableFarVbo.upload(buildableFarBuffer); + + long endTime = System.currentTimeMillis(); + long buildTime = endTime - startTime; + if (buildTime > 1000) { - // don't add null chunkPos (which shouldn't happen anyway) - // or add more to the generation queue - if(chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) - break; - - // TODO add a list of locations we are waiting to generate so we don't add the same position to the queue multiple times - - numberOfChunksWaitingToGenerate.addAndGet(1); - - LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, renderer, LodQuadTreeNodeBuilder, this, lodDim, serverWorld); - WorldWorkerManager.addWorker(genWorker); + ClientProxy.LOGGER.info("\"LodNodeBufferBuilder.generateLodBuffersAsync\" took " + buildTime + " milliseconds, consider lowering the render quality."); } + + // mark that the buildable buffers as ready to swap + switchVbos = true; + } + catch (Exception e) + { + ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: " + e.getMessage()); + e.printStackTrace(); + } + finally + { + // regardless of if we successfully created the buffers or not + // we are done generating. + generatingBuffers = false; } - // finish the buffer building - buildableNearBuffer.end(); - buildableFarBuffer.end(); - - // mark that the buildable buffers as ready to swap - generatingBuffers = false; - switchBuffers = true; }); genThread.execute(thread); @@ -410,30 +440,36 @@ public class LodNodeBufferBuilder { buildableNearBuffer = new BufferBuilder(bufferMaxCapacity); buildableFarBuffer = new BufferBuilder(bufferMaxCapacity); + + buildableNearVbo = new VertexBuffer(LodNodeRenderer.LOD_VERTEX_FORMAT); + buildableFarVbo = new VertexBuffer(LodNodeRenderer.LOD_VERTEX_FORMAT); + + drawableNearVbo = new VertexBuffer(LodNodeRenderer.LOD_VERTEX_FORMAT); + drawableFarVbo = new VertexBuffer(LodNodeRenderer.LOD_VERTEX_FORMAT); } /** - * Swap the drawable and buildable buffers and return - * the old drawable buffers. - * @param drawableNearBuffer - * @param drawableFarBuffer + * Get the newly created VBOs */ - public NearFarBuffer swapBuffers(BufferBuilder drawableNearBuffer, BufferBuilder drawableFarBuffer) + public NearFarVbos getVertexBuffers() { - // swap the BufferBuilders - BufferBuilder tmp = buildableNearBuffer; - buildableNearBuffer = drawableNearBuffer; - drawableNearBuffer = tmp; + NearFarVbos vbos = new NearFarVbos(buildableNearVbo, buildableFarVbo); - tmp = buildableFarBuffer; - buildableFarBuffer = drawableFarBuffer; - drawableFarBuffer = tmp; + VertexBuffer tmp = null; + + tmp = drawableNearVbo; + drawableNearVbo = buildableNearVbo; + buildableNearVbo = tmp; + + tmp = buildableNearVbo; + buildableNearVbo = drawableNearVbo; + drawableNearVbo = tmp; - // the buffers have been swapped - switchBuffers = false; + // the vbos have been swapped + switchVbos = false; - return new NearFarBuffer(drawableNearBuffer, drawableFarBuffer); + return vbos; } /** @@ -443,7 +479,7 @@ public class LodNodeBufferBuilder */ public boolean newBuffersAvaliable() { - return switchBuffers; + return switchVbos; } diff --git a/src/main/java/com/seibel/lod/objects/NearFarBuffer.java b/src/main/java/com/seibel/lod/objects/NearFarVbos.java similarity index 73% rename from src/main/java/com/seibel/lod/objects/NearFarBuffer.java rename to src/main/java/com/seibel/lod/objects/NearFarVbos.java index efbd105c2..070d2bbd6 100644 --- a/src/main/java/com/seibel/lod/objects/NearFarBuffer.java +++ b/src/main/java/com/seibel/lod/objects/NearFarVbos.java @@ -17,7 +17,7 @@ */ package com.seibel.lod.objects; -import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.vertex.VertexBuffer; /** * This object is just a replacement for an array @@ -25,21 +25,21 @@ import net.minecraft.client.renderer.BufferBuilder; * and BuildBufferThread. * * @author James Seibel - * @version 03-25-2021 + * @version 08-15-2021 */ -public class NearFarBuffer +public class NearFarVbos { - public BufferBuilder nearBuffer; + public VertexBuffer nearVbo; - public BufferBuilder farBuffer; + public VertexBuffer farVbo; /** - * @param newNearBuffer - * @param newFarBuffer + * @param newNearVbo + * @param newFarVbo */ - public NearFarBuffer(BufferBuilder newNearBuffer, BufferBuilder newFarBuffer) + public NearFarVbos(VertexBuffer newNearVbo, VertexBuffer newFarVbo) { - nearBuffer = newNearBuffer; - farBuffer = newFarBuffer; + nearVbo = newNearVbo; + farVbo = newFarVbo; } } diff --git a/src/main/java/com/seibel/lod/render/LodNodeRenderer.java b/src/main/java/com/seibel/lod/render/LodNodeRenderer.java index 74c5ceaf6..6d3d0cbd9 100644 --- a/src/main/java/com/seibel/lod/render/LodNodeRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodNodeRenderer.java @@ -37,15 +37,14 @@ import com.seibel.lod.handlers.LodConfig; import com.seibel.lod.handlers.ReflectionHandler; import com.seibel.lod.objects.LodQuadTreeDimension; import com.seibel.lod.objects.LodQuadTreeNode; -import com.seibel.lod.objects.NearFarBuffer; import com.seibel.lod.objects.NearFarFogSettings; +import com.seibel.lod.objects.NearFarVbos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.util.LodUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.FogRenderer; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.WorldRenderer; @@ -67,7 +66,7 @@ import net.minecraft.util.math.vector.Vector3f; * This is where LODs are draw to the world. * * @author James Seibel - * @version 07-4-2021 + * @version 8-15-2021 */ public class LodNodeRenderer { @@ -106,16 +105,11 @@ public class LodNodeRenderer /** This is used to generate the buildable buffers */ private LodNodeBufferBuilder lodNodeBufferBuilder; - - /** The buffers that are used to draw LODs using near fog */ - private volatile BufferBuilder drawableNearBuffer; - /** The buffers that are used to draw LODs using far fog */ - private volatile BufferBuilder drawableFarBuffer; - + /** This is the VertexBuffer used to draw any LODs that use near fog */ - private volatile VertexBuffer nearVbo; + private VertexBuffer nearVbo; /** This is the VertexBuffer used to draw any LODs that use far fog */ - private volatile VertexBuffer farVbo; + private VertexBuffer farVbo; public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR; @@ -254,8 +248,7 @@ public class LodNodeRenderer if (regen && !lodNodeBufferBuilder.generatingBuffers && !lodNodeBufferBuilder.newBuffersAvaliable()) { // this will mainly happen when the view distance is changed - if (drawableNearBuffer == null || drawableFarBuffer == null || - previousChunkRenderDistance != mc.options.renderDistance) + if (previousChunkRenderDistance != mc.options.renderDistance) setupBuffers(numbChunksWide); // generate the LODs on a separate thread to prevent stuttering or freezing @@ -636,9 +629,6 @@ public class LodNodeRenderer bufferMemory = RenderUtil.getBufferMemoryForRadiusMultiplier(maxRadiusMultiplier); } - drawableNearBuffer = new BufferBuilder(bufferMemory); - drawableFarBuffer = new BufferBuilder(bufferMemory); - lodNodeBufferBuilder.setupBuffers(bufferMemory); } @@ -661,31 +651,18 @@ public class LodNodeRenderer /** - * Replace the current drawable buffers with the newly + * Replace the current Vertex Buffers with the newly * created buffers from the lodBufferBuilder. */ private void swapBuffers() { // replace the drawable buffers with // the newly created buffers from the lodBufferBuilder - NearFarBuffer newBuffers = lodNodeBufferBuilder.swapBuffers(drawableNearBuffer, drawableFarBuffer); - drawableNearBuffer = newBuffers.nearBuffer; - drawableFarBuffer = newBuffers.farBuffer; + NearFarVbos newVbos = lodNodeBufferBuilder.getVertexBuffers(); - - // bind the buffers with their respective VBOs - if (nearVbo != null) - nearVbo.close(); - - nearVbo = new VertexBuffer(LOD_VERTEX_FORMAT); - nearVbo.upload(drawableNearBuffer); - - - if (farVbo != null) - farVbo.close(); - - farVbo = new VertexBuffer(LOD_VERTEX_FORMAT); - farVbo.upload(drawableFarBuffer); + // bind the buffers with their respective VBOs + nearVbo = newVbos.nearVbo; + farVbo = newVbos.farVbo; }