From a391f34ab72f7df3b486f854b9d446949c06eb6c Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:46:16 +1000 Subject: [PATCH] Textures almost working, fixed up the mesher being a dumbass --- .../cortex/zenith/client/core/VoxelCore.java | 8 +-- .../client/core/model/ModelManager.java | 59 ++++++++++++++++++- .../rendering/AbstractFarWorldRenderer.java | 2 +- .../core/rendering/Gl46FarWorldRenderer.java | 40 +++++++------ .../zenith/client/core/util/Mesher2D.java | 41 ++++++++----- .../zenith/shaders/lod/gl46/bindings.glsl | 4 ++ .../assets/zenith/shaders/lod/gl46/quads.frag | 7 ++- .../assets/zenith/shaders/lod/gl46/quads.vert | 18 ++---- 8 files changed, 121 insertions(+), 58 deletions(-) diff --git a/src/main/java/me/cortex/zenith/client/core/VoxelCore.java b/src/main/java/me/cortex/zenith/client/core/VoxelCore.java index 9d713523..bc2bf13a 100644 --- a/src/main/java/me/cortex/zenith/client/core/VoxelCore.java +++ b/src/main/java/me/cortex/zenith/client/core/VoxelCore.java @@ -99,7 +99,7 @@ public class VoxelCore { this.firstTime = false; } this.distanceTracker.setCenter(camera.getBlockPos().getX(), camera.getBlockPos().getY(), camera.getBlockPos().getZ()); - //this.renderer.setupRender(frustum, camera); + this.renderer.setupRender(frustum, camera); } public void renderOpaque(MatrixStack matrices, double cameraX, double cameraY, double cameraZ) { @@ -109,7 +109,7 @@ public class VoxelCore { matrices.pop(); //this.renderer.getModelManager().updateEntry(0, Blocks.COMPARATOR.getDefaultState()); - this.renderer.getModelManager().updateEntry(0, Blocks.OAK_LEAVES.getDefaultState()); + //this.renderer.getModelManager().updateEntry(0, Blocks.OAK_LEAVES.getDefaultState()); //int boundFB = GlStateManager.getBoundFramebuffer(); //this.postProcessing.setSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight); @@ -123,8 +123,8 @@ public class VoxelCore { //TODO: have the renderer also render a bounding full face just like black boarders around lvl 0 // this is cause the terrain might not exist and so all the caves are visible causing hell for the // occlusion culler - if (false) - this.renderer.renderFarAwayOpaque(matrices, cameraX, cameraY, cameraZ); + + this.renderer.renderFarAwayOpaque(matrices, cameraX, cameraY, cameraZ); //glBindFramebuffer(GL_FRAMEBUFFER, boundFB); diff --git a/src/main/java/me/cortex/zenith/client/core/model/ModelManager.java b/src/main/java/me/cortex/zenith/client/core/model/ModelManager.java index 179c408a..2165e331 100644 --- a/src/main/java/me/cortex/zenith/client/core/model/ModelManager.java +++ b/src/main/java/me/cortex/zenith/client/core/model/ModelManager.java @@ -1,19 +1,40 @@ package me.cortex.zenith.client.core.model; +import com.mojang.blaze3d.platform.GlStateManager; import me.cortex.zenith.client.core.gl.GlBuffer; +import me.cortex.zenith.client.core.gl.GlTexture; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.color.block.BlockColors; import net.minecraft.registry.Registries; +import org.lwjgl.opengl.GL45C; + +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11C.GL_NEAREST; +import static org.lwjgl.opengl.GL11C.GL_NEAREST_MIPMAP_LINEAR; +import static org.lwjgl.opengl.GL12C.GL_TEXTURE_MAX_LOD; +import static org.lwjgl.opengl.GL12C.GL_TEXTURE_MIN_LOD; +import static org.lwjgl.opengl.GL33.glDeleteSamplers; +import static org.lwjgl.opengl.GL33.glGenSamplers; +import static org.lwjgl.opengl.GL33C.glSamplerParameteri; +import static org.lwjgl.opengl.GL45C.glTextureSubImage2D; //Manages the storage and updating of model states, textures and colours //Also has a fast long[] based metadata lookup for when the terrain mesher needs to look up the face occlusion data + +//TODO: support more than 65535 states, what should actually happen is a blockstate is registered, the model data is generated, then compared +// to all other models already loaded, if it is a duplicate, create a mapping from the id to the already loaded id, this will help with meshing aswell +// as leaves and such will be able to be merged public class ModelManager { public static final int MODEL_SIZE = 64; - private final ModelTextureBakery bakery = new ModelTextureBakery(16, 16); + private final ModelTextureBakery bakery; private final GlBuffer modelBuffer; + private final GlTexture textures; + private final int blockSampler = glGenSamplers(); + //Model data might also contain a constant colour if the colour resolver produces a constant colour, this saves space in the + // section buffer reverse indexing //The Meta-cache contains critical information needed for meshing, colour provider bit, per-face = is empty, has alpha, is solid, full width, full height // alpha means that some pixels have alpha values and belong in the translucent rendering layer, @@ -38,9 +59,24 @@ public class ModelManager { // this has an issue with scaffolding i believe tho, so maybe make it a probability to render??? idk private final long[] metadataCache; - public ModelManager() { + //Provides a map from id -> model id as multiple ids might have the same internal model id + private final int[] idMappings; + private final int modelTextureSize; + + public ModelManager(int modelTextureSize) { + this.modelTextureSize = modelTextureSize; + this.bakery = new ModelTextureBakery(modelTextureSize, modelTextureSize); this.modelBuffer = new GlBuffer(MODEL_SIZE * (1<<16)); + //TODO: figure out how to do mipping :blobfox_pineapple: + this.textures = new GlTexture().store(GL_RGBA8, 1, modelTextureSize*3*256,modelTextureSize*2*256); this.metadataCache = new long[1<<16]; + this.idMappings = new int[1<<16]; + + + glSamplerParameteri(this.blockSampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + glSamplerParameteri(this.blockSampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glSamplerParameteri(this.blockSampler, GL_TEXTURE_MIN_LOD, 0); + glSamplerParameteri(this.blockSampler, GL_TEXTURE_MAX_LOD, 4); } public void updateEntry(int id, BlockState blockState) { @@ -64,6 +100,16 @@ public class ModelManager { } + private void putTextures(int id, ColourDepthTextureData[] textures) { + int X = (id&0xFF) * this.modelTextureSize*3; + int Y = ((id>>8)&0xFF) * this.modelTextureSize*2; + for (int subTex = 0; subTex < 6; subTex++) { + + + //glTextureSubImage2D(this.textures.id, 0, ); + } + } + public long getModelMetadata(int id) { return this.metadataCache[id]; } @@ -72,8 +118,17 @@ public class ModelManager { return this.modelBuffer.id; } + public int getTextureId() { + return this.textures.id; + } + public int getSamplerId() { + return this.blockSampler; + } + public void free() { this.bakery.free(); this.modelBuffer.free(); + this.textures.free(); + glDeleteSamplers(this.blockSampler); } } diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/AbstractFarWorldRenderer.java b/src/main/java/me/cortex/zenith/client/core/rendering/AbstractFarWorldRenderer.java index 91a208d3..b2b41dae 100644 --- a/src/main/java/me/cortex/zenith/client/core/rendering/AbstractFarWorldRenderer.java +++ b/src/main/java/me/cortex/zenith/client/core/rendering/AbstractFarWorldRenderer.java @@ -47,7 +47,7 @@ public abstract class AbstractFarWorldRenderer { this.uniformBuffer = new GlBuffer(1024); this.lightDataBuffer = new GlBuffer(256*4);//256 of uint this.geometry = new GeometryManager(geometrySize*8L, maxSections); - this.models = new ModelManager(); + this.models = new ModelManager(16); } protected abstract void setupVao(); diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/Gl46FarWorldRenderer.java b/src/main/java/me/cortex/zenith/client/core/rendering/Gl46FarWorldRenderer.java index 5d6ff069..2cd8b431 100644 --- a/src/main/java/me/cortex/zenith/client/core/rendering/Gl46FarWorldRenderer.java +++ b/src/main/java/me/cortex/zenith/client/core/rendering/Gl46FarWorldRenderer.java @@ -1,5 +1,6 @@ package me.cortex.zenith.client.core.rendering; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import me.cortex.zenith.client.core.gl.GlBuffer; import me.cortex.zenith.client.core.gl.shader.Shader; @@ -10,6 +11,8 @@ import net.minecraft.client.render.RenderLayer; import net.minecraft.client.util.math.MatrixStack; import org.joml.Matrix4f; import org.joml.Vector3f; +import org.lwjgl.opengl.GL11C; +import org.lwjgl.opengl.GL45C; import org.lwjgl.system.MemoryUtil; import java.util.List; @@ -17,6 +20,7 @@ import java.util.List; import static org.lwjgl.opengl.ARBMultiDrawIndirect.glMultiDrawElementsIndirect; import static org.lwjgl.opengl.GL11.GL_TRIANGLES; import static org.lwjgl.opengl.GL11.GL_UNSIGNED_SHORT; +import static org.lwjgl.opengl.GL11.glGetInteger; import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30C.GL_R8UI; import static org.lwjgl.opengl.GL30C.GL_RED_INTEGER; @@ -77,6 +81,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { return; } RenderLayer.getCutoutMipped().startDrawing(); + int oldActiveTexture = glGetInteger(GL_ACTIVE_TEXTURE); + int oldBoundTexture = glGetInteger(GL_TEXTURE_BINDING_2D); //RenderSystem.enableBlend(); //RenderSystem.defaultBlendFunc(); @@ -85,32 +91,23 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { UploadStream.INSTANCE.commit(); glBindVertexArray(this.vao); + + + //Bind the texture atlas + glBindSampler(0, this.models.getSamplerId()); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, this.models.getTextureId()); + + this.commandGen.bind(); glDispatchCompute((this.geometry.getSectionCount() + 127) / 128, 1, 1); glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT); this.lodShader.bind(); - if (false) {//Bloody intel gpus - glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0, 1000, 0); - - //int count = this.geometry.getSectionCount()/1000; - //for (int i = 0; i < 10; i++) { - // glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, i*1000L*20, 1000, 0); - //} - //int rem = this.geometry.getSectionCount() - (count*1000); - //if (rem != 0) { - // glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, count*1000L*20, rem, 0); - //} - - } else { - //TODO: swap to a multidraw indirect counted - glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0, this.geometry.getSectionCount(), 0); - } + glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0, this.geometry.getSectionCount(), 0); //ARBIndirectParameters.glMultiDrawElementsIndirectCountARB( glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT); - //TODO: add gpu occlusion culling here (after the lod drawing) (maybe, finish the rest of the PoC first) - cullShader.bind(); glColorMask(false, false, false, false); @@ -124,8 +121,13 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { glColorMask(true, true, true, true); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - glBindVertexArray(0); + //TODO: need to do temporal rasterization here + + glBindVertexArray(0); + glBindSampler(0, 0); + GL11C.glBindTexture(GL_TEXTURE_2D, oldBoundTexture); + glActiveTexture(oldActiveTexture); RenderLayer.getCutoutMipped().endDrawing(); } diff --git a/src/main/java/me/cortex/zenith/client/core/util/Mesher2D.java b/src/main/java/me/cortex/zenith/client/core/util/Mesher2D.java index 8977f476..08461b3b 100644 --- a/src/main/java/me/cortex/zenith/client/core/util/Mesher2D.java +++ b/src/main/java/me/cortex/zenith/client/core/util/Mesher2D.java @@ -81,7 +81,7 @@ public class Mesher2D { while (ex || ez) { //Expand in the x direction if (ex) { - if (endX + 1 > this.maxSize || endX+1 == (1 << this.size) - 1) { + if (endX - x >= this.maxSize || endX >= (1 << this.size) - 1) { ex = false; } } @@ -96,7 +96,7 @@ public class Mesher2D { endX++; } if (ez) { - if (endZ + 1 > this.maxSize || endZ+1 == (1<= this.maxSize || endZ >= (1< #import -layout(location = 0) out flat vec4 colour; +layout(location = 0) out vec2 uv; uint extractLodLevel() { return uint(gl_BaseInstance)>>29; @@ -41,7 +41,8 @@ void main() { cornerIdx ^= 1; } - ivec2 size = extractSize(quad) * ivec2((cornerIdx>>1)&1, cornerIdx&1) * (1<>1)&1, cornerIdx&1); + ivec2 size = sizePreLod * (1<>1)&1)+10),1); //uint i = uint(quad>>32);