Close issue #37 (z-fighting far from the origin)
I'm not certain why in LodRenderer swapBuffers has to be called after the frame has been rendered, but otherwise it causes stuttering / rubber banding.
This commit is contained in:
@@ -49,7 +49,7 @@ import net.minecraft.util.math.ChunkPos;
|
||||
* This object is used to create NearFarBuffer objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-24-2021
|
||||
* @version 9-6-2021
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
@@ -107,7 +107,13 @@ public class LodBufferBuilder
|
||||
|
||||
private volatile Object[][] 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);
|
||||
|
||||
|
||||
public LodBufferBuilder()
|
||||
{
|
||||
|
||||
@@ -159,11 +165,8 @@ public class LodBufferBuilder
|
||||
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;
|
||||
@@ -173,7 +176,10 @@ public class LodBufferBuilder
|
||||
|
||||
if (setsToRender.length != lodDim.regions.length)
|
||||
setsToRender = new Object[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
|
||||
// this will be the center of the VBOs once they have been built
|
||||
buildableCenterChunkPos = playerChunkPos;
|
||||
|
||||
|
||||
RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ());
|
||||
if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0)
|
||||
@@ -293,8 +299,8 @@ public class LodBufferBuilder
|
||||
}
|
||||
}
|
||||
posToRender.changeParameters(detailLevel, posX, posZ);
|
||||
|
||||
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPos, lodData, adjData,
|
||||
|
||||
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, lodData, adjData,
|
||||
posToRender, renderer.previousDebugMode);
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
@@ -338,7 +344,7 @@ public class LodBufferBuilder
|
||||
// ClientProxy.LOGGER.info("Buffer Build time: " + buildTime + " ms" + '\n' +
|
||||
// "Tree cutting time: " + treeTime + " ms" + '\n' +
|
||||
// "Rendering time: " + renderingTime + " ms");
|
||||
|
||||
|
||||
// mark that the buildable buffers as ready to swap
|
||||
switchVbos = true;
|
||||
} catch (Exception e)
|
||||
@@ -361,7 +367,7 @@ public class LodBufferBuilder
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
mainGenThread.execute(thread);
|
||||
|
||||
return;
|
||||
@@ -571,7 +577,7 @@ public class LodBufferBuilder
|
||||
/**
|
||||
* Get the newly created VBOs
|
||||
*/
|
||||
public VertexBuffer[][] getVertexBuffers()
|
||||
public VertexBuffersAndOffset getVertexBuffers()
|
||||
{
|
||||
// don't wait for the lock to open
|
||||
// since this is called on the main render thread
|
||||
@@ -580,13 +586,29 @@ public class LodBufferBuilder
|
||||
VertexBuffer[][] tmp = drawableVbos;
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmp;
|
||||
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
return drawableVbos;
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos);
|
||||
}
|
||||
/**
|
||||
* A simple container to pass multiple objects back in the getVertexBuffers method.
|
||||
*/
|
||||
public class VertexBuffersAndOffset
|
||||
{
|
||||
public VertexBuffer[][] vbos;
|
||||
public ChunkPos drawableCenterChunkPos;
|
||||
|
||||
public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos)
|
||||
{
|
||||
vbos = newVbos;
|
||||
drawableCenterChunkPos = newDrawableCenterChunkPos;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
* Builds LODs as rectangular prisms.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-10-2021
|
||||
* @version 9-6-2021
|
||||
*/
|
||||
public class CubicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@@ -47,7 +47,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, DebugMode debugging)
|
||||
{
|
||||
AxisAlignedBB bbox;
|
||||
@@ -61,7 +61,8 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
width,
|
||||
levelPos.posX * width,
|
||||
0,
|
||||
levelPos.posZ * width);
|
||||
levelPos.posZ * width,
|
||||
bufferCenterBlockPos);
|
||||
|
||||
int color = DataPoint.getColor(data);
|
||||
if (debugging != DebugMode.OFF)
|
||||
@@ -71,12 +72,12 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
|
||||
if (bbox != null)
|
||||
{
|
||||
addBoundingBoxToBuffer(buffer, bbox, color, playerBlockPos, adjData);
|
||||
addBoundingBoxToBuffer(buffer, bbox, color, bufferCenterBlockPos, adjData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset)
|
||||
private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset, BlockPos bufferCenterBlockPos)
|
||||
{
|
||||
// don't add an LOD if it is empty
|
||||
if (height == -1 && depth == -1)
|
||||
@@ -89,7 +90,13 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
height++;
|
||||
}
|
||||
|
||||
return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset);
|
||||
// offset the AABB by it's x/z position in the world since
|
||||
// it uses doubles to specify its location, unlike the model view matrix
|
||||
// which only uses floats
|
||||
double x = -bufferCenterBlockPos.getX();
|
||||
double z = -bufferCenterBlockPos.getZ();
|
||||
|
||||
return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset).move(x, 0, z);
|
||||
}
|
||||
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, int c, BlockPos playerBlockPos, short[][][] adjData)
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.builders.LodBufferBuilder;
|
||||
import com.seibel.lod.builders.LodBufferBuilder.VertexBuffersAndOffset;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
@@ -56,6 +57,7 @@ import net.minecraft.entity.Entity;
|
||||
import net.minecraft.potion.EffectInstance;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
@@ -68,7 +70,7 @@ import net.minecraft.util.math.vector.Vector3f;
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-31-2021
|
||||
* @version 9-6-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
@@ -120,7 +122,7 @@ public class LodRenderer
|
||||
*/
|
||||
private VertexBuffer[][] vbos;
|
||||
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
|
||||
|
||||
private ChunkPos vbosCenter = new ChunkPos(0,0);
|
||||
|
||||
/**
|
||||
* This is used to determine if the LODs should be regenerated
|
||||
@@ -228,14 +230,6 @@ public class LodRenderer
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
// ...ending here
|
||||
|
||||
// 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())
|
||||
{
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
@@ -346,6 +340,18 @@ public class LodRenderer
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
profiler.pop();
|
||||
}
|
||||
@@ -490,10 +496,17 @@ public class LodRenderer
|
||||
// generate the model view matrix
|
||||
MatrixStack matrixStack = new MatrixStack();
|
||||
matrixStack.pushPose();
|
||||
// translate and rotate to the current camera location
|
||||
// rotate to the current camera's direction
|
||||
matrixStack.mulPose(Vector3f.XP.rotationDegrees(renderInfo.getXRot()));
|
||||
matrixStack.mulPose(Vector3f.YP.rotationDegrees(renderInfo.getYRot() + 180));
|
||||
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
|
||||
// translate the camera relative to the regions' center
|
||||
// (AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
// accuracy vs the model view matrix, which only uses floats)
|
||||
BlockPos bufferPos = vbosCenter.getWorldPosition();
|
||||
Vector3d eyePos = mc.getPlayer().getEyePosition(partialTicks);
|
||||
double xDiff = eyePos.x - bufferPos.getX();
|
||||
double zDiff = eyePos.z - bufferPos.getZ();
|
||||
matrixStack.translate(-xDiff, -projectedView.y, -zDiff);
|
||||
|
||||
return matrixStack.last().pose();
|
||||
}
|
||||
@@ -638,13 +651,18 @@ public class LodRenderer
|
||||
|
||||
/**
|
||||
* Replace the current Vertex Buffers with the newly
|
||||
* created buffers from the lodBufferBuilder.
|
||||
* created buffers from the lodBufferBuilder. <br><br>
|
||||
*
|
||||
* For some reason this has to be called after the frame has been rendered,
|
||||
* otherwise visual stuttering/rubber banding may happen. I'm not sure why...
|
||||
*/
|
||||
private void swapBuffers()
|
||||
{
|
||||
// replace the drawable buffers with
|
||||
// the newly created buffers from the lodBufferBuilder
|
||||
vbos = lodBufferBuilder.getVertexBuffers();
|
||||
VertexBuffersAndOffset result = lodBufferBuilder.getVertexBuffers();
|
||||
vbos = result.vbos;
|
||||
vbosCenter = result.drawableCenterChunkPos;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user