From 0b88a6f824c1a6933a1c3cf947de17a95e7e8dc2 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Thu, 1 May 2025 23:24:41 +1000 Subject: [PATCH] Added min chunk bounds + fix other bugs in model baking and other places --- .../voxy/client/core/VoxyRenderSystem.java | 38 +++++++----- .../core/model/ModelBakerySubsystem.java | 11 +++- .../voxy/client/core/model/ModelFactory.java | 4 +- .../core/model/bakery/ModelTextureBakery.java | 10 +++- .../core/rendering/ChunkBoundRenderer.java | 26 ++++++-- .../client/core/rendering/RenderService.java | 14 +++-- .../core/rendering/post/PostProcessing.java | 11 ++-- .../section/AbstractSectionRenderer.java | 8 ++- .../section/MDICSectionRenderer.java | 25 +++++--- .../rendering/util/SharedIndexBuffer.java | 59 +++++++++++++++++- .../voxy/client/core/util/IndexUtil.java | 60 ------------------- .../mixin/minecraft/MixinWorldRenderer.java | 2 +- .../sodium/MixinDefaultChunkRenderer.java | 5 +- .../sodium/MixinRenderSectionManager.java | 26 +++++++- .../voxy/shaders/chunkoutline/outline.vsh | 10 ++-- .../assets/voxy/shaders/lod/gl46/quads.frag | 5 ++ 16 files changed, 189 insertions(+), 125 deletions(-) delete mode 100644 src/main/java/me/cortex/voxy/client/core/util/IndexUtil.java diff --git a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java index 8672d266..f3609659 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java @@ -7,6 +7,7 @@ import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.client.core.gl.Capabilities; import me.cortex.voxy.client.core.gl.GlBuffer; import me.cortex.voxy.client.core.model.ModelBakerySubsystem; +import me.cortex.voxy.client.core.rendering.ChunkBoundRenderer; import me.cortex.voxy.client.core.rendering.RenderDistanceTracker; import me.cortex.voxy.client.core.rendering.RenderService; import me.cortex.voxy.client.core.rendering.building.RenderDataFactory45; @@ -22,6 +23,7 @@ import me.cortex.voxy.common.world.WorldEngine; import me.cortex.voxy.common.world.WorldSection; import me.cortex.voxy.common.world.other.Mapper; import me.cortex.voxy.commonImpl.VoxyCommon; +import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.GlBackend; @@ -29,6 +31,7 @@ import net.minecraft.client.render.Camera; import net.minecraft.client.render.Frustum; import net.minecraft.client.util.math.MatrixStack; import org.joml.Matrix4f; +import org.joml.Matrix4fc; import org.lwjgl.opengl.GL11; import java.util.ArrayList; @@ -45,6 +48,7 @@ public class VoxyRenderSystem { private final PostProcessing postProcessing; private final WorldEngine worldIn; private final RenderDistanceTracker renderDistanceTracker; + public final ChunkBoundRenderer chunkBoundRenderer; public VoxyRenderSystem(WorldEngine world, ServiceThreadPool threadPool) { //Trigger the shared index buffer loading @@ -62,6 +66,8 @@ public class VoxyRenderSystem { this.renderer::removeTopLevelNode); this.renderDistanceTracker.setRenderDistance(VoxyConfig.CONFIG.sectionRenderDistance); + + this.chunkBoundRenderer = new ChunkBoundRenderer(); } public void setRenderDistance(int renderDistance) { @@ -130,13 +136,14 @@ public class VoxyRenderSystem { } //TODO: Make a reverse z buffer - private static Matrix4f computeProjectionMat() { - return new Matrix4f(RenderSystem.getProjectionMatrix()).mulLocal( - makeProjectionMatrix(0.05f, MinecraftClient.getInstance().gameRenderer.getFarPlaneDistance()).invert() + private static Matrix4f computeProjectionMat(Matrix4fc base) { + return base.mulLocal( + makeProjectionMatrix(0.05f, MinecraftClient.getInstance().gameRenderer.getFarPlaneDistance()).invert(), + new Matrix4f() ).mulLocal(makeProjectionMatrix(16, 16*3000)); } - public void renderOpaque(MatrixStack matrices, double cameraX, double cameraY, double cameraZ) { + public void renderOpaque(ChunkRenderMatrices matrices, double cameraX, double cameraY, double cameraZ) { if (IrisUtil.irisShadowActive()) { return; } @@ -165,17 +172,13 @@ public class VoxyRenderSystem { cameraY += (16+(256-32-sector*30))*16; } - matrices.push(); - matrices.translate(-cameraX, -cameraY, -cameraZ); - matrices.pop(); - - var projection = computeProjectionMat();//RenderSystem.getProjectionMatrix(); - //var projection = RenderSystem.getProjectionMatrix(); + var projection = computeProjectionMat(matrices.projection());//RenderSystem.getProjectionMatrix(); + //var projection = new Matrix4f(matrices.projection()); var viewport = this.renderer.getViewport(); viewport .setProjection(projection) - .setModelView(matrices.peek().getPositionMatrix()) + .setModelView(new Matrix4f(matrices.modelView())) .setCamera(cameraX, cameraY, cameraZ) .setScreenSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight) .update(); @@ -190,22 +193,25 @@ public class VoxyRenderSystem { if (boundFB == 0) { throw new IllegalStateException("Cannot use the default framebuffer as cannot source from it"); } + + this.chunkBoundRenderer.render(viewport); + //TODO: use the raw depth buffer texture instead //int boundDepthBuffer = glGetNamedFramebufferAttachmentParameteri(boundFB, GL_DEPTH_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); //TODO:FIXME!!! ?? this.postProcessing.setup(target.textureWidth, target.textureHeight, boundFB); - this.renderer.renderFarAwayOpaque(viewport); + this.renderer.renderFarAwayOpaque(viewport, this.chunkBoundRenderer.getDepthBoundTexture()); //Compute the SSAO of the rendered terrain, TODO: fix it breaking depth or breaking _something_ am not sure what - this.postProcessing.computeSSAO(projection, matrices); + this.postProcessing.computeSSAO(viewport.MVP); //We can render the translucent directly after as it is the furthest translucent objects - this.renderer.renderFarAwayTranslucent(viewport); + this.renderer.renderFarAwayTranslucent(viewport, this.chunkBoundRenderer.getDepthBoundTexture()); - this.postProcessing.renderPost(projection, RenderSystem.getProjectionMatrix(), boundFB); + this.postProcessing.renderPost(projection, matrices.projection(), boundFB); glBindFramebuffer(GlConst.GL_FRAMEBUFFER, oldFB); TimingStatistics.main.stop(); TimingStatistics.all.stop(); @@ -225,7 +231,7 @@ public class VoxyRenderSystem { Logger.info("Flushing download stream"); DownloadStream.INSTANCE.flushWaitClear(); Logger.info("Shutting down rendering"); - try {this.renderer.shutdown();} catch (Exception e) {Logger.error("Error shutting down renderer", e);} + try {this.renderer.shutdown();this.chunkBoundRenderer.free();} catch (Exception e) {Logger.error("Error shutting down renderer", e);} Logger.info("Shutting down post processor"); if (this.postProcessing!=null){try {this.postProcessing.shutdown();} catch (Exception e) {Logger.error("Error shutting down post processor", e);}} } diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java b/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java index 685edfea..e5bd061e 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java @@ -73,9 +73,14 @@ public class ModelBakerySubsystem { long budget = Math.min(totalBudget-200_000, totalBudget-(this.factory.resultJobs.size()*20_000L))-200_000; if (budget > 50_000) { Integer i = this.blockIdQueue.poll(); - while (i != null && (System.nanoTime() - start < budget)) { - this.factory.addEntry(i); - i = this.blockIdQueue.poll(); + if (i != null) { + do { + this.factory.addEntry(i); + i = this.blockIdQueue.poll(); + } while (i != null && (System.nanoTime() - start < budget)); + if (i != null) {//We timedout on our budget and we have an entry so we must add it back + this.blockIdQueue.add(i); + } } } } diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java index 8551c30d..b80685b2 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java @@ -619,12 +619,12 @@ public class ModelFactory { for (var dir : Direction.values()) { var data = textures[dir.getIndex()]; float fd = TextureUtils.computeDepth(data, TextureUtils.DEPTH_MODE_AVG, checkMode);//Compute the min float depth, smaller means closer to the camera, range 0-1 - int depth = Math.round(fd * MODEL_TEXTURE_SIZE); + //int depth = Math.round(fd * MODEL_TEXTURE_SIZE); //If fd is -1, it means that there was nothing rendered on that face and it should be discarded if (fd < -0.1) { res[dir.ordinal()] = -1; } else { - res[dir.ordinal()] = ((float) depth)/MODEL_TEXTURE_SIZE; + res[dir.ordinal()] = fd;//((float) depth)/MODEL_TEXTURE_SIZE; } } return res; diff --git a/src/main/java/me/cortex/voxy/client/core/model/bakery/ModelTextureBakery.java b/src/main/java/me/cortex/voxy/client/core/model/bakery/ModelTextureBakery.java index 4a365eea..6146a7d4 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/bakery/ModelTextureBakery.java +++ b/src/main/java/me/cortex/voxy/client/core/model/bakery/ModelTextureBakery.java @@ -187,6 +187,12 @@ public class ModelTextureBakery { glBindFramebuffer(GL_FRAMEBUFFER, originalFramebuffer); } + private static boolean shouldReturnAirForFluid(BlockPos pos, int face) { + var fv = Direction.byIndex(face).getVector(); + int dot = fv.getX()*pos.getX() + fv.getY()*pos.getY() + fv.getZ()*pos.getZ(); + return dot >= 1; + } + private final BufferAllocator allocator = new BufferAllocator(786432); private void rasterView(BlockState state, BlockStateModel model, Matrix4f transform, long randomValue, int face, boolean renderFluid, GpuTexture texture, boolean hasDiscard) { var bb = new BufferBuilder(this.allocator, VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR) { @@ -244,7 +250,7 @@ public class ModelTextureBakery { @Override public BlockState getBlockState(BlockPos pos) { - if (pos.equals(Direction.byIndex(face).getVector())) { + if (shouldReturnAirForFluid(pos, face)) { return Blocks.AIR.getDefaultState(); } @@ -262,7 +268,7 @@ public class ModelTextureBakery { @Override public FluidState getFluidState(BlockPos pos) { - if (pos.equals(Direction.byIndex(face).getVector())) { + if (shouldReturnAirForFluid(pos, face)) { return Blocks.AIR.getDefaultState().getFluidState(); } //if (pos.getY() == 1) { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java index 1ae09125..d1bd7ea0 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/ChunkBoundRenderer.java @@ -8,6 +8,8 @@ import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.rendering.util.SharedIndexBuffer; import me.cortex.voxy.client.core.rendering.util.UploadStream; +import me.cortex.voxy.common.Logger; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; import org.joml.Matrix4f; import org.joml.Vector3i; @@ -19,6 +21,7 @@ import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER; import static org.lwjgl.opengl.GL15.glBindBuffer; import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30C.*; +import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER; import static org.lwjgl.opengl.GL31.glDrawElementsInstanced; import static org.lwjgl.opengl.GL45.glClearNamedFramebufferfv; @@ -49,7 +52,8 @@ public class ChunkBoundRenderer { throw new IllegalStateException("At capacity"); } if (this.chunk2idx.containsKey(pos)) { - throw new IllegalArgumentException("Chunk already in map"); + Logger.warn("Chunk already in map: " + new ChunkPos(pos)); + return; } int idx = this.chunk2idx.size(); this.chunk2idx.put(pos, idx); @@ -65,9 +69,10 @@ public class ChunkBoundRenderer { public void removeChunk(long pos) { int idx = this.chunk2idx.remove(pos); if (idx == -1) { - throw new IllegalArgumentException("Chunk pos not in map"); + Logger.warn("Chunk not in map: " + new ChunkPos(pos)); + return; } - if (idx == this.chunk2idx.size()-1) { + if (idx == this.chunk2idx.size()) { //Dont need to do anything as heap is already compact return; } @@ -92,6 +97,8 @@ public class ChunkBoundRenderer { //Bind and render, changing as little gl state as possible so that the caller may configure how it wants to render public void render(Viewport viewport) { + if (this.chunk2idx.isEmpty()) return; + if (this.depthBuffer.getWidth() != viewport.width || this.depthBuffer.getHeight() != viewport.height) { this.depthBuffer.free(); this.depthBuffer = new GlTexture().store(GL_DEPTH_COMPONENT24, 1, viewport.width, viewport.height); @@ -129,7 +136,10 @@ public class ChunkBoundRenderer { glBindVertexArray(RenderService.STATIC_VAO); glBindFramebuffer(GL_FRAMEBUFFER, this.frameBuffer.id); this.rasterShader.bind(); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE.id()); + //TODO: BATCH with multiple cubes per instance, this helps fill the pipe and should greatly improve performance of this + glDrawElementsInstanced(GL_TRIANGLES, 6*2*3, GL_UNSIGNED_BYTE, SharedIndexBuffer.CUBE_INDEX_OFFSET, this.chunk2idx.size()); { @@ -139,10 +149,14 @@ public class ChunkBoundRenderer { //TODO: check this is correct glEnable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); } } + public void reset() { + this.chunk2idx.clear(); + } + public void free() { this.depthBuffer.free(); this.frameBuffer.free(); @@ -151,4 +165,8 @@ public class ChunkBoundRenderer { this.uniformBuffer.free(); this.chunkPosBuffer.free(); } + + public GlTexture getDepthBoundTexture() { + return this.depthBuffer; + } } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java b/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java index 2fa5bb1b..eb02f393 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java @@ -4,6 +4,7 @@ import io.netty.util.internal.MathUtil; import me.cortex.voxy.client.RenderStatistics; import me.cortex.voxy.client.TimingStatistics; import me.cortex.voxy.client.core.gl.Capabilities; +import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.model.ModelBakerySubsystem; import me.cortex.voxy.client.core.model.ModelStore; import me.cortex.voxy.client.core.rendering.building.BuiltSection; @@ -58,7 +59,7 @@ public class RenderService, J extends Vi //Max geometry: 1 gb long geometryCapacity = Math.min((1L<<(64-Long.numberOfLeadingZeros(Capabilities.INSTANCE.ssboMaxSize-1)))<<1, 1L<<32)-1024/*(1L<<32)-1024*/; - // geometryCapacity = 1<<24; + //geometryCapacity = 1<<24; //Max sections: ~500k this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, geometryCapacity); Logger.info("Using renderer: " + this.sectionRenderer.getClass().getSimpleName()); @@ -106,7 +107,7 @@ public class RenderService, J extends Vi this.modelService.tick(); } - public void renderFarAwayOpaque(J viewport) { + public void renderFarAwayOpaque(J viewport, GlTexture depthBoundTexture) { //LightMapHelper.tickLightmap(); //Render previous geometry with the abstract renderer @@ -117,7 +118,7 @@ public class RenderService, J extends Vi // the section renderer is as it might have different backends, but they all accept a buffer containing the section list - this.sectionRenderer.renderOpaque(viewport); + this.sectionRenderer.renderOpaque(viewport, depthBoundTexture); //NOTE: need to do the upload and download tick here, after the section renderer renders the world, to ensure "stable" @@ -174,11 +175,12 @@ public class RenderService, J extends Vi } this.traversal.doTraversal(viewport, depthBuffer); - this.sectionRenderer.buildDrawCallsAndRenderTemporal(viewport, this.traversal.getRenderListBuffer()); + this.sectionRenderer.buildDrawCalls(viewport, this.traversal.getRenderListBuffer()); + this.sectionRenderer.renderTemporal(depthBoundTexture); } - public void renderFarAwayTranslucent(J viewport) { - this.sectionRenderer.renderTranslucent(viewport); + public void renderFarAwayTranslucent(J viewport, GlTexture depthBoundTexture) { + this.sectionRenderer.renderTranslucent(viewport, depthBoundTexture); } public void addDebugData(List debug) { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/post/PostProcessing.java b/src/main/java/me/cortex/voxy/client/core/rendering/post/PostProcessing.java index 2872fdaa..6f963333 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/post/PostProcessing.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/post/PostProcessing.java @@ -7,6 +7,7 @@ import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.rendering.util.GlStateCapture; import net.minecraft.client.util.math.MatrixStack; import org.joml.Matrix4f; +import org.joml.Matrix4fc; import org.lwjgl.opengl.GL11C; import static org.lwjgl.opengl.ARBComputeShader.glDispatchCompute; @@ -136,16 +137,14 @@ public class PostProcessing { //Computes ssao on the current framebuffer data and updates it // this means that translucency wont be effected etc - public void computeSSAO(Matrix4f projection, MatrixStack stack) { + public void computeSSAO(Matrix4f mvp) { this.didSSAO = true; this.ssaoComp.bind(); float[] data = new float[4*4]; - var mat = new Matrix4f(projection).mul(stack.peek().getPositionMatrix()); - mat.get(data); + mvp.get(data); glUniformMatrix4fv(3, false, data);//MVP - mat.invert(); - mat.get(data); + mvp.invert(new Matrix4f()).get(data); glUniformMatrix4fv(4, false, data);//invMVP glBindImageTexture(0, this.colourSSAO.id, 0, false,0, GL_READ_WRITE, GL_RGBA8); @@ -159,7 +158,7 @@ public class PostProcessing { //Executes the post processing and emits to whatever framebuffer is currently bound via a blit - public void renderPost(Matrix4f fromProjection, Matrix4f tooProjection, int outputFB) { + public void renderPost(Matrix4f fromProjection, Matrix4fc tooProjection, int outputFB) { glDisable(GL_STENCIL_TEST); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionRenderer.java index 6fb8e5ec..258c62cc 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionRenderer.java @@ -2,6 +2,7 @@ package me.cortex.voxy.client.core.rendering.section; import me.cortex.voxy.client.core.gl.GlBuffer; +import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.model.ModelStore; import me.cortex.voxy.client.core.rendering.Viewport; @@ -16,9 +17,10 @@ public abstract class AbstractSectionRenderer , J extends this.modelStore = modelStore; } - public abstract void renderOpaque(T viewport); - public abstract void buildDrawCallsAndRenderTemporal(T viewport, GlBuffer sectionRenderList); - public abstract void renderTranslucent(T viewport); + public abstract void renderOpaque(T viewport, GlTexture depthBoundTexture); + public abstract void buildDrawCalls(T viewport, GlBuffer sectionRenderList); + public abstract void renderTemporal(GlTexture depthBoundTexture); + public abstract void renderTranslucent(T viewport, GlTexture depthBoundTexture); public abstract T createViewport(); public void free() { this.geometryManager.free(); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java index 7373b1d6..816ef7ef 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java @@ -3,6 +3,7 @@ package me.cortex.voxy.client.core.rendering.section; import me.cortex.voxy.client.RenderStatistics; import me.cortex.voxy.client.core.gl.GlBuffer; +import me.cortex.voxy.client.core.gl.GlTexture; import me.cortex.voxy.client.core.gl.shader.Shader; import me.cortex.voxy.client.core.gl.shader.ShaderType; import me.cortex.voxy.client.core.model.ModelStore; @@ -100,27 +101,28 @@ public class MDICSectionRenderer extends AbstractSectionRenderer= 1<<8) { + throw new IllegalArgumentException("Quad count to large"); + } + MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L); + long ptr = buffer.address; + for(int i = 0; i < quadCount*4; i += 4) { + MemoryUtil.memPutByte(ptr + (0), (byte) (i + 1)); + MemoryUtil.memPutByte(ptr + (1), (byte) (i + 2)); + MemoryUtil.memPutByte(ptr + (2), (byte) (i + 0)); + MemoryUtil.memPutByte(ptr + (3), (byte) (i + 1)); + MemoryUtil.memPutByte(ptr + (4), (byte) (i + 3)); + MemoryUtil.memPutByte(ptr + (5), (byte) (i + 2)); + + ptr += 6; + } + + return buffer; + } + public static MemoryBuffer generateQuadIndicesShort(int quadCount) { + if ((quadCount*4) >= 1<<16) { + throw new IllegalArgumentException("Quad count to large"); + } + MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L * 2); + long ptr = buffer.address; + for(int i = 0; i < quadCount*4; i += 4) { + MemoryUtil.memPutShort(ptr + (0*2), (short) (i + 1)); + MemoryUtil.memPutShort(ptr + (1*2), (short) (i + 2)); + MemoryUtil.memPutShort(ptr + (2*2), (short) (i + 0)); + MemoryUtil.memPutShort(ptr + (3*2), (short) (i + 1)); + MemoryUtil.memPutShort(ptr + (4*2), (short) (i + 3)); + MemoryUtil.memPutShort(ptr + (5*2), (short) (i + 2)); + + ptr += 6 * 2; + } + + return buffer; + } + + public static MemoryBuffer generateQuadIndicesInt(int quadCount) { + MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L * 2); + long ptr = buffer.address; + for(int i = 0; i < quadCount*4; i += 4) { + MemoryUtil.memPutInt(ptr + (0*4), i); + MemoryUtil.memPutInt(ptr + (1*4), (i + 1)); + MemoryUtil.memPutInt(ptr + (2*4), (i + 2)); + MemoryUtil.memPutInt(ptr + (3*4), (i + 1)); + MemoryUtil.memPutInt(ptr + (4*4), (i + 3)); + MemoryUtil.memPutInt(ptr + (5*4), (i + 2)); + ptr += 6 * 4; + } + return buffer; + } + public int id() { return this.indexBuffer.id; } diff --git a/src/main/java/me/cortex/voxy/client/core/util/IndexUtil.java b/src/main/java/me/cortex/voxy/client/core/util/IndexUtil.java deleted file mode 100644 index a9a975d4..00000000 --- a/src/main/java/me/cortex/voxy/client/core/util/IndexUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -package me.cortex.voxy.client.core.util; - -import me.cortex.voxy.common.util.MemoryBuffer; -import org.lwjgl.system.MemoryUtil; - -public class IndexUtil { - public static MemoryBuffer generateQuadIndicesByte(int quadCount) { - if ((quadCount*4) >= 1<<8) { - throw new IllegalArgumentException("Quad count to large"); - } - MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L); - long ptr = buffer.address; - for(int i = 0; i < quadCount*4; i += 4) { - MemoryUtil.memPutByte(ptr + (0), (byte) (i + 1)); - MemoryUtil.memPutByte(ptr + (1), (byte) (i + 2)); - MemoryUtil.memPutByte(ptr + (2), (byte) (i + 0)); - MemoryUtil.memPutByte(ptr + (3), (byte) (i + 1)); - MemoryUtil.memPutByte(ptr + (4), (byte) (i + 3)); - MemoryUtil.memPutByte(ptr + (5), (byte) (i + 2)); - - ptr += 6; - } - - return buffer; - } - public static MemoryBuffer generateQuadIndicesShort(int quadCount) { - if ((quadCount*4) >= 1<<16) { - throw new IllegalArgumentException("Quad count to large"); - } - MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L * 2); - long ptr = buffer.address; - for(int i = 0; i < quadCount*4; i += 4) { - MemoryUtil.memPutShort(ptr + (0*2), (short) (i + 1)); - MemoryUtil.memPutShort(ptr + (1*2), (short) (i + 2)); - MemoryUtil.memPutShort(ptr + (2*2), (short) (i + 0)); - MemoryUtil.memPutShort(ptr + (3*2), (short) (i + 1)); - MemoryUtil.memPutShort(ptr + (4*2), (short) (i + 3)); - MemoryUtil.memPutShort(ptr + (5*2), (short) (i + 2)); - - ptr += 6 * 2; - } - - return buffer; - } - - public static MemoryBuffer generateQuadIndicesInt(int quadCount) { - MemoryBuffer buffer = new MemoryBuffer(quadCount * 6L * 2); - long ptr = buffer.address; - for(int i = 0; i < quadCount*4; i += 4) { - MemoryUtil.memPutInt(ptr + (0*4), i); - MemoryUtil.memPutInt(ptr + (1*4), (i + 1)); - MemoryUtil.memPutInt(ptr + (2*4), (i + 2)); - MemoryUtil.memPutInt(ptr + (3*4), (i + 1)); - MemoryUtil.memPutInt(ptr + (4*4), (i + 3)); - MemoryUtil.memPutInt(ptr + (5*4), (i + 2)); - ptr += 6 * 4; - } - return buffer; - } -} diff --git a/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinWorldRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinWorldRenderer.java index 3e30f471..60c7b4a5 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinWorldRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/minecraft/MixinWorldRenderer.java @@ -38,7 +38,7 @@ public abstract class MixinWorldRenderer implements IGetVoxyRenderSystem { return this.renderer; } - @Inject(method = "reload()V", at = @At("TAIL")) + @Inject(method = "reload()V", at = @At("RETURN"), order = 900)//We want to inject before sodium private void reloadVoxyRenderer(CallbackInfo ci) { this.shutdownRenderer(); if (this.world != null) { diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java index 9329d58f..7b9f5017 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java @@ -24,10 +24,7 @@ public class MixinDefaultChunkRenderer { if (renderPass == DefaultTerrainRenderPasses.CUTOUT) { var renderer = ((IGetVoxyRenderSystem) MinecraftClient.getInstance().worldRenderer).getVoxyRenderSystem(); if (renderer != null) { - var stack = new MatrixStack(); - stack.loadIdentity(); - stack.multiplyPositionMatrix(new Matrix4f(matrices.modelView())); - renderer.renderOpaque(stack, camera.x, camera.y, camera.z); + renderer.renderOpaque(matrices, camera.x, camera.y, camera.z); } } } diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java index 300df3ef..303228a2 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderSectionManager.java @@ -1,11 +1,14 @@ package me.cortex.voxy.client.mixin.sodium; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import me.cortex.voxy.client.VoxyClientInstance; import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.client.core.IGetVoxyRenderSystem; import me.cortex.voxy.commonImpl.VoxyCommon; +import net.caffeinemc.mods.sodium.client.gl.device.CommandList; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.ChunkPos; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -17,12 +20,22 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public class MixinRenderSectionManager { @Shadow @Final private ClientWorld level; + @Inject(method = "", at = @At("TAIL")) + private void voxy$resetChunkTracker(ClientWorld level, int renderDistance, CommandList commandList, CallbackInfo ci) { + if (level.worldRenderer != null) { + var system = ((IGetVoxyRenderSystem)(level.worldRenderer)).getVoxyRenderSystem(); + if (system != null) { + system.chunkBoundRenderer.reset(); + } + } + } + @Inject(method = "onChunkAdded", at = @At("HEAD")) private void voxy$trackChunkAdd(int x, int z, CallbackInfo ci) { if (this.level.worldRenderer != null) { var system = ((IGetVoxyRenderSystem)(this.level.worldRenderer)).getVoxyRenderSystem(); if (system != null) { - + system.chunkBoundRenderer.addChunk(ChunkPos.toLong(x, z)); } } } @@ -32,7 +45,7 @@ public class MixinRenderSectionManager { if (this.level.worldRenderer != null) { var system = ((IGetVoxyRenderSystem)(this.level.worldRenderer)).getVoxyRenderSystem(); if (system != null) { - + system.chunkBoundRenderer.removeChunk(ChunkPos.toLong(x, z)); } } } @@ -52,4 +65,13 @@ public class MixinRenderSectionManager { } } } + + + @ModifyReturnValue(method = "getSearchDistance", at = @At("RETURN")) + private float voxy$increaseSearchDistanceFix(float searchDistance) { + if (((IGetVoxyRenderSystem)(this.level.worldRenderer)).getVoxyRenderSystem() == null) { + return searchDistance; + } + return searchDistance + 20; + } } diff --git a/src/main/resources/assets/voxy/shaders/chunkoutline/outline.vsh b/src/main/resources/assets/voxy/shaders/chunkoutline/outline.vsh index 74a96791..81dbd780 100644 --- a/src/main/resources/assets/voxy/shaders/chunkoutline/outline.vsh +++ b/src/main/resources/assets/voxy/shaders/chunkoutline/outline.vsh @@ -11,11 +11,13 @@ layout(binding = 1, std430) restrict readonly buffer ChunkPosBuffer { }; void main() { + ivec3 origin = ivec3(chunkPos[gl_InstanceID], 0).xzy; + origin -= section.xyz; + ivec3 cubeCornerI = ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1); - cubeCornerI.xz += chunkPos[gl_InstanceID]; //Expand the y height to be big (will be +- 8192) //TODO: make it W.R.T world height and offsets - cubeCornerI.y = cubeCornerI.y*1024-512; - cubeCornerI -= section.xyz; - gl_Position = MVP * vec4(vec3(cubeCornerI*16), 1); + cubeCornerI.y = cubeCornerI.y*32-16; + gl_Position = MVP * vec4(vec3(cubeCornerI+origin)*16, 1); + gl_Position.z -= 0.0001f; } \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag index c0ea4b4e..9d8b13d8 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/quads.frag @@ -1,5 +1,6 @@ #version 460 core layout(binding = 0) uniform sampler2D blockModelAtlas; +layout(binding = 2) uniform sampler2D depthTex; //#define DEBUG_RENDER @@ -19,6 +20,10 @@ layout(location = 6) in flat uint quadDebug; #endif layout(location = 0) out vec4 outColour; void main() { + //Check the minimum bounding texture and ensure we are greater than it + if (gl_FragCoord.z < texelFetch(depthTex, ivec2(gl_FragCoord.xy), 0).r) { + discard; + } vec2 uv = mod(uv, vec2(1.0))*(1.0/(vec2(3.0,2.0)*256.0)); //vec4 colour = solidColour; vec4 colour = texture(blockModelAtlas, uv + baseUV, ((flags>>1)&1u)*-4.0);