From 8860feb58a5b117e0ae565cc247ed7aab34f7bef Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Tue, 30 Jan 2024 21:51:33 +1000 Subject: [PATCH] Began work on biome colouring --- .../cortex/zenith/client/core/VoxelCore.java | 7 ++++ .../client/core/model/ModelManager.java | 42 +++++++++++++++++-- .../core/rendering/Gl46FarWorldRenderer.java | 3 +- .../common/world/ActiveSectionTracker.java | 2 + .../zenith/shaders/lod/gl46/bindings.glsl | 6 ++- .../zenith/shaders/lod/gl46/block_model.glsl | 4 ++ .../assets/zenith/shaders/lod/gl46/quads.vert | 14 ++++--- 7 files changed, 68 insertions(+), 10 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 db995986..57509479 100644 --- a/src/main/java/me/cortex/zenith/client/core/VoxelCore.java +++ b/src/main/java/me/cortex/zenith/client/core/VoxelCore.java @@ -13,6 +13,9 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Frustum; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.util.Identifier; import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; @@ -72,6 +75,10 @@ public class VoxelCore { ////Resave the db incase it failed a recovery //this.world.getMapper().forceResaveStates(); + var biomeRegistry = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BIOME); + for (var biome : this.world.getMapper().getBiomeEntries()) { + this.renderer.getModelManager().addBiome(biome.id, biomeRegistry.get(new Identifier(biome.biome))); + } for (var state : this.world.getMapper().getStateEntries()) { this.renderer.getModelManager().addEntry(state.id, state.state); 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 a783ea7f..f844c7a3 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 @@ -16,6 +16,7 @@ import net.minecraft.client.render.RenderLayers; import net.minecraft.fluid.FluidState; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryKeys; +import net.minecraft.util.Pair; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; @@ -40,6 +41,7 @@ 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.glGenerateTextureMipmap; import static org.lwjgl.opengl.GL45C.glTextureSubImage2D; //Manages the storage and updating of model states, textures and colours @@ -53,6 +55,7 @@ public class ModelManager { public static final int MODEL_SIZE = 64; private final ModelTextureBakery bakery; private final GlBuffer modelBuffer; + private final GlBuffer modelColourBuffer; private final GlTexture textures; private final int blockSampler = glGenSamplers(); @@ -91,12 +94,20 @@ public class ModelManager { private final int[] idMappings; private final Object2IntOpenHashMap> modelTexture2id = new Object2IntOpenHashMap<>(); + + private final List biomes = new ArrayList<>(); + private final List> modelsRequiringBiomeColours = new ArrayList<>(); + + public ModelManager(int modelTextureSize) { this.modelTextureSize = modelTextureSize; this.bakery = new ModelTextureBakery(modelTextureSize, modelTextureSize); this.modelBuffer = new GlBuffer(MODEL_SIZE * (1<<16)); + + this.modelColourBuffer = new GlBuffer(4 * (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.textures = new GlTexture().store(GL_RGBA8, 4, modelTextureSize*3*256,modelTextureSize*2*256); this.metadataCache = new long[1<<16]; this.idMappings = new int[1<<20];//Max of 1 million blockstates mapping to 65k model states Arrays.fill(this.idMappings, -1); @@ -263,11 +274,18 @@ public class ModelManager { //Temporary override to always be non biome specific if (colourProvider == null) { MemoryUtil.memPutInt(uploadPtr + 4, -1);//Set the default to nothing so that its faster on the gpu - } else if ((!hasBiomeColourResolver) || true) { + } else if (!hasBiomeColourResolver) { Biome defaultBiome = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BIOME).get(BiomeKeys.PLAINS); MemoryUtil.memPutInt(uploadPtr + 4, captureColourConstant(colourProvider, blockState, defaultBiome)|0xFF000000); - } else { + } else if (!this.biomes.isEmpty()) { //Populate the list of biomes for the model state + int biomeIndex = this.modelsRequiringBiomeColours.size() * this.biomes.size(); + MemoryUtil.memPutInt(uploadPtr + 4, biomeIndex); + this.modelsRequiringBiomeColours.add(new Pair<>(modelId, blockState)); + long clrUploadPtr = UploadStream.INSTANCE.upload(this.modelColourBuffer, biomeIndex * 4L, 4L * this.biomes.size()); + for (var biome : this.biomes) { + MemoryUtil.memPutInt(clrUploadPtr, captureColourConstant(colourProvider, blockState, biome)|0xFF000000); clrUploadPtr += 4; + } } @@ -277,9 +295,21 @@ public class ModelManager { this.putTextures(modelId, textureData); + + glGenerateTextureMipmap(this.textures.id); return modelId; } + public void addBiome(int id, Biome biome) { + this.biomes.add(biome); + if (this.biomes.size()-1 != id) { + throw new IllegalStateException("Biome ordering not consistent with biome id"); + } + + //TODO: Need to invalidate teh entire colour buffer and reuploadd + } + + //TODO: add a method to detect biome dependent colours (can do by detecting if getColor is ever called) // if it is, need to add it to a list and mark it as biome colour dependent or something then the shader // will either use the uint as an index or a direct colour multiplier @@ -388,6 +418,7 @@ public class ModelManager { + public static boolean faceExists(long metadata, int face) { return ((metadata>>(8*face))&0xFF)!=0xFF; } @@ -510,9 +541,14 @@ public class ModelManager { return this.blockSampler; } + public int getColourBufferId() { + return this.modelColourBuffer.id; + } + public void free() { this.bakery.free(); this.modelBuffer.free(); + this.modelColourBuffer.free(); this.textures.free(); glDeleteSamplers(this.blockSampler); } 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 3369d4cf..70f85764 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 @@ -81,7 +81,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, this.geometry.metaId()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, this.glVisibilityBuffer.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.models.getBufferId()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, this.lightDataBuffer.id);//Lighting LUT + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, this.models.getColourBufferId()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, this.lightDataBuffer.id);//Lighting LUT glBindVertexArray(0); } diff --git a/src/main/java/me/cortex/zenith/common/world/ActiveSectionTracker.java b/src/main/java/me/cortex/zenith/common/world/ActiveSectionTracker.java index 5e41bf07..91dbceba 100644 --- a/src/main/java/me/cortex/zenith/common/world/ActiveSectionTracker.java +++ b/src/main/java/me/cortex/zenith/common/world/ActiveSectionTracker.java @@ -11,6 +11,8 @@ public class ActiveSectionTracker { private final Long2ObjectOpenHashMap>[] loadedSectionCache; private final SectionLoader loader; + + @SuppressWarnings("unchecked") public ActiveSectionTracker(int layers, SectionLoader loader) { this.loader = loader; this.loadedSectionCache = new Long2ObjectOpenHashMap[layers]; diff --git a/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl b/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl index 608d2583..3f59c552 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl @@ -71,7 +71,11 @@ layout(binding = 6, std430) readonly restrict buffer ModelBuffer { BlockModel modelData[]; }; -layout(binding = 7, std430) readonly restrict buffer LightingBuffer { +layout(binding = 7, std430) readonly restrict buffer ModelColourBuffer { + uint colourData[]; +}; + +layout(binding = 8, std430) readonly restrict buffer LightingBuffer { uint lightData[]; }; diff --git a/src/main/resources/assets/zenith/shaders/lod/gl46/block_model.glsl b/src/main/resources/assets/zenith/shaders/lod/gl46/block_model.glsl index b87b101c..ac1cc3c0 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/block_model.glsl +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/block_model.glsl @@ -14,4 +14,8 @@ uint faceHasAlphaCuttout(uint faceData) { uint faceHasAlphaCuttoutOverride(uint faceData) { return (faceData>>23)&1; +} + +bool modelHasBiomeLUT(BlockModel model) { + return ((model.flagsA)&2) != 0; } \ No newline at end of file diff --git a/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert b/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert index 4c4b0953..be14a59d 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert @@ -66,25 +66,25 @@ void main() { vec3 offset = vec3(size, (float(face&1) + getDepthOffset(faceData, face)) * (1<>1) == 0) {//Up/down + if ((face>>1) == 0) { //Up/down offset = offset.xzy; } //Not needed, here for readability //if ((face>>1) == 1) {//north/south // offset = offset.xyz; //} - if ((face>>1) == 2) {//west/east + if ((face>>1) == 2) { //west/east offset = offset.zxy; } - gl_Position = MVP * vec4(corner + offset,1); + gl_Position = MVP * vec4(corner + offset, 1); //Compute the uv coordinates vec2 modelUV = vec2(modelId&0xFF, (modelId>>8)&0xFF)*(1f/(256f)); //TODO: make the face orientated by 2x3 so that division is not a integer div and modulo isnt needed // as these are very slow ops - baseUV = modelUV + (vec2(face%3, face/3) * (1f/(vec2(3,2)*256f))); + baseUV = modelUV + (vec2(face%3, face/3) * (1f/(vec2(3, 2)*256f))); uv = respectiveQuadSize + faceOffset;//Add in the face offset for 0,0 uv discardAlpha = faceHasAlphaCuttout(faceData); @@ -96,7 +96,11 @@ void main() { colourTinting = getLighting(extractLightId(quad)); //Apply model colour tinting - colourTinting *= uint2vec4RGBA(model.colourTint).yzwx; + uint tintColour = model.colourTint; + if (modelHasBiomeLUT(model)) { + tintColour = colourData[tintColour + extractBiomeId(quad)]; + } + colourTinting *= uint2vec4RGBA(tintColour).yzwx; //Apply face tint if (face == 0) {