From dd953fc77428c70a1c6e0a704c13db4f714fbb33 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Wed, 24 Jan 2024 22:49:55 +1000 Subject: [PATCH] Began major engineering on texturing --- build.gradle | 4 +- .../cortex/zenith/client/core/VoxelCore.java | 46 ++---- .../zenith/client/core/gl/GlBuffer.java | 5 + .../zenith/client/core/gl/GlFramebuffer.java | 3 +- .../core/model/ColourDepthTextureData.java | 4 + .../client/core/model/ModelManager.java | 37 +++++ .../client/core/model/ModelTextureBakery.java | 142 ++++++++++++++++++ .../client/core/model/TextureUtils.java | 46 ++++++ .../zenith/client/core/other/BiomeColour.java | 4 - .../client/core/other/BlockStateColour.java | 4 - .../client/core/other/ColourResolver.java | 138 ----------------- .../rendering/AbstractFarWorldRenderer.java | 52 ++----- .../core/rendering/GeometryManager.java | 2 +- .../core/rendering/Gl46FarWorldRenderer.java | 13 +- .../client/core/rendering/ModelManager.java | 5 - .../core/rendering/NvFarWorldRenderer.java | 55 ------- .../core/rendering/SharedIndexBuffer.java | 2 +- .../core/rendering/util/BufferArena.java | 2 +- .../zenith/client/core/util/DebugUtil.java | 2 +- .../zenith/shaders/lod/gl46/bindings.glsl | 18 +-- .../assets/zenith/shaders/lod/gl46/quads.vert | 11 +- 21 files changed, 273 insertions(+), 322 deletions(-) create mode 100644 src/main/java/me/cortex/zenith/client/core/model/ColourDepthTextureData.java create mode 100644 src/main/java/me/cortex/zenith/client/core/model/ModelManager.java create mode 100644 src/main/java/me/cortex/zenith/client/core/model/ModelTextureBakery.java create mode 100644 src/main/java/me/cortex/zenith/client/core/model/TextureUtils.java delete mode 100644 src/main/java/me/cortex/zenith/client/core/other/BiomeColour.java delete mode 100644 src/main/java/me/cortex/zenith/client/core/other/BlockStateColour.java delete mode 100644 src/main/java/me/cortex/zenith/client/core/other/ColourResolver.java delete mode 100644 src/main/java/me/cortex/zenith/client/core/rendering/ModelManager.java delete mode 100644 src/main/java/me/cortex/zenith/client/core/rendering/NvFarWorldRenderer.java diff --git a/build.gradle b/build.gradle index 6423647b..bca206be 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,9 @@ dependencies { modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation "maven.modrinth:sodium:mc1.20.3-0.5.5" + //TODO: this is to eventually not need sodium installed as atm its just used for parsing shaders + modRuntimeOnly "maven.modrinth:sodium:mc1.20.3-0.5.5" + modCompileOnly "maven.modrinth:sodium:mc1.20.3-0.5.5" modImplementation("maven.modrinth:cloth-config:13.0.121+fabric") modImplementation("maven.modrinth:modmenu:9.0.0") 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 eb5d4c79..312163aa 100644 --- a/src/main/java/me/cortex/zenith/client/core/VoxelCore.java +++ b/src/main/java/me/cortex/zenith/client/core/VoxelCore.java @@ -1,23 +1,20 @@ package me.cortex.zenith.client.core; -import me.cortex.zenith.client.Zenith; import me.cortex.zenith.client.config.ZenithConfig; +import me.cortex.zenith.client.core.model.ModelTextureBakery; +import me.cortex.zenith.client.core.model.TextureUtils; import me.cortex.zenith.client.core.rendering.*; import me.cortex.zenith.client.core.rendering.building.RenderGenerationService; import me.cortex.zenith.client.core.util.DebugUtil; import me.cortex.zenith.common.world.WorldEngine; -import me.cortex.zenith.client.core.other.BiomeColour; -import me.cortex.zenith.client.core.other.BlockStateColour; -import me.cortex.zenith.client.core.other.ColourResolver; -import me.cortex.zenith.common.world.other.Mapper; import me.cortex.zenith.client.importers.WorldImporter; import me.cortex.zenith.common.world.storage.FragmentedStorageBackendAdaptor; import net.minecraft.block.Block; import net.minecraft.block.Blocks; +import net.minecraft.block.CropBlock; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Frustum; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.math.Direction; import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; @@ -83,39 +80,11 @@ public class VoxelCore { this.postProcessing = null;//new PostProcessing(); - this.world.getMapper().setCallbacks(this::stateUpdate, this::biomeUpdate); - - for (var state : this.world.getMapper().getStateEntries()) { - this.stateUpdate(state); - } - - for (var biome : this.world.getMapper().getBiomeEntries()) { - this.biomeUpdate(biome); - } - System.out.println("Entry updates applied"); + this.world.getMapper().setCallbacks(a->{}, a->{}); System.out.println("Voxel core initialized"); } - private void stateUpdate(Mapper.StateEntry entry) { - var state = entry.state; - int tintMsk = 0; - if (biomeTintableAllFaces.contains(state.getBlock())) { - tintMsk |= (1<<6)-1; - } - if (biomeTintableUpFace.contains(state.getBlock())) { - tintMsk |= 1<>32))); - } public void enqueueIngest(WorldChunk worldChunk) { @@ -129,7 +98,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) { @@ -138,6 +107,8 @@ public class VoxelCore { DebugUtil.setPositionMatrix(matrices); matrices.pop(); + renderer.getModelManager().updateEntry(0, Blocks.FERN.getDefaultState()); + //int boundFB = GlStateManager.getBoundFramebuffer(); //this.postProcessing.setSize(MinecraftClient.getInstance().getFramebuffer().textureWidth, MinecraftClient.getInstance().getFramebuffer().textureHeight); //this.postProcessing.bindClearFramebuffer(); @@ -150,7 +121,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 - this.renderer.renderFarAwayOpaque(matrices, cameraX, cameraY, cameraZ); + if (false) + this.renderer.renderFarAwayOpaque(matrices, cameraX, cameraY, cameraZ); //glBindFramebuffer(GL_FRAMEBUFFER, boundFB); diff --git a/src/main/java/me/cortex/zenith/client/core/gl/GlBuffer.java b/src/main/java/me/cortex/zenith/client/core/gl/GlBuffer.java index e27fb45e..83535e71 100644 --- a/src/main/java/me/cortex/zenith/client/core/gl/GlBuffer.java +++ b/src/main/java/me/cortex/zenith/client/core/gl/GlBuffer.java @@ -10,6 +10,11 @@ import static org.lwjgl.opengl.GL45C.glNamedBufferStorage; public class GlBuffer extends TrackedObject { public final int id; private final long size; + + public GlBuffer(long size) { + this(size, 0); + } + public GlBuffer(long size, int flags) { this.id = glCreateBuffers(); this.size = size; diff --git a/src/main/java/me/cortex/zenith/client/core/gl/GlFramebuffer.java b/src/main/java/me/cortex/zenith/client/core/gl/GlFramebuffer.java index 620a33ae..5adf2f37 100644 --- a/src/main/java/me/cortex/zenith/client/core/gl/GlFramebuffer.java +++ b/src/main/java/me/cortex/zenith/client/core/gl/GlFramebuffer.java @@ -21,10 +21,11 @@ public class GlFramebuffer extends TrackedObject { glDeleteFramebuffers(this.id); } - public void verify() { + public GlFramebuffer verify() { int code; if ((code = glCheckNamedFramebufferStatus(this.id, GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { throw new IllegalStateException("Framebuffer incomplete with error code: " + code); } + return this; } } diff --git a/src/main/java/me/cortex/zenith/client/core/model/ColourDepthTextureData.java b/src/main/java/me/cortex/zenith/client/core/model/ColourDepthTextureData.java new file mode 100644 index 00000000..b3685847 --- /dev/null +++ b/src/main/java/me/cortex/zenith/client/core/model/ColourDepthTextureData.java @@ -0,0 +1,4 @@ +package me.cortex.zenith.client.core.model; + +public record ColourDepthTextureData(int[] colour, int[] depth) { +} 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 new file mode 100644 index 00000000..04f93ca8 --- /dev/null +++ b/src/main/java/me/cortex/zenith/client/core/model/ModelManager.java @@ -0,0 +1,37 @@ +package me.cortex.zenith.client.core.model; + +import me.cortex.zenith.client.core.gl.GlBuffer; +import net.minecraft.block.BlockState; + +//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 +public class ModelManager { + public static final int MODEL_SIZE = 64; + private final ModelTextureBakery bakery = new ModelTextureBakery(16, 16); + private final GlBuffer modelBuffer; + private final long[] metadataCache; + + public ModelManager() { + this.modelBuffer = new GlBuffer(MODEL_SIZE * (1<<16)); + this.metadataCache = new long[1<<16]; + } + + public void updateEntry(int id, BlockState blockState) { + //This also checks if there is a block colour resolver for the given blockstate and marks that the block has a resolver + var textureData = this.bakery.renderFaces(blockState, 123456); + } + + public long getModelMetadata(int id) { + return this.metadataCache[id]; + } + + public int getBufferId() { + return this.modelBuffer.id; + } + + public void free() { + this.bakery.free(); + this.modelBuffer.free(); + } +} diff --git a/src/main/java/me/cortex/zenith/client/core/model/ModelTextureBakery.java b/src/main/java/me/cortex/zenith/client/core/model/ModelTextureBakery.java new file mode 100644 index 00000000..b2093013 --- /dev/null +++ b/src/main/java/me/cortex/zenith/client/core/model/ModelTextureBakery.java @@ -0,0 +1,142 @@ +package me.cortex.zenith.client.core.model; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.systems.VertexSorter; +import me.cortex.zenith.client.core.gl.GlFramebuffer; +import me.cortex.zenith.client.core.gl.GlTexture; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.*; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.RotationAxis; +import net.minecraft.util.math.random.LocalRandom; +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL11C; + +import java.util.ArrayList; +import java.util.List; + +import static org.lwjgl.opengl.ARBFramebufferObject.*; +import static org.lwjgl.opengl.ARBShaderImageLoadStore.GL_FRAMEBUFFER_BARRIER_BIT; +import static org.lwjgl.opengl.ARBShaderImageLoadStore.glMemoryBarrier; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL14C.glBlendFuncSeparate; +import static org.lwjgl.opengl.GL45C.glBlitNamedFramebuffer; +import static org.lwjgl.opengl.GL45C.glGetTextureImage; + +//Builds a texture for each face of a model +public class ModelTextureBakery { + private final int width; + private final int height; + private final GlTexture colourTex; + private final GlTexture depthTex; + private final GlFramebuffer framebuffer; + + private static final List FACE_VIEWS = new ArrayList<>(); + static { + addView(-90,0);//Direction.DOWN + addView(90,0);//Direction.UP + addView(0,180);//Direction.NORTH + addView(0,0);//Direction.SOUTH + //TODO: check these arnt the wrong way round + addView(0,90);//Direction.EAST + addView(0,270);//Direction.WEST + } + + public ModelTextureBakery(int width, int height) { + this.width = width; + this.height = height; + this.colourTex = new GlTexture().store(GL_RGBA8, 1, width, height); + this.depthTex = new GlTexture().store(GL_DEPTH24_STENCIL8, 1, width, height); + this.framebuffer = new GlFramebuffer().bind(GL_COLOR_ATTACHMENT0, this.colourTex).bind(GL_DEPTH_STENCIL_ATTACHMENT, this.depthTex).verify(); + } + + private static void addView(float pitch, float yaw) { + var stack = new MatrixStack(); + stack.translate(0.5f,0.5f,0); + stack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(pitch)); + stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw)); + stack.translate(-0.5f,-0.5f,-0.5f); + FACE_VIEWS.add(stack); + } + + public ColourDepthTextureData[] renderFaces(BlockState state, long randomValue) { + var model = MinecraftClient.getInstance() + .getBakedModelManager() + .getBlockModels() + .getModel(state); + + int oldFB = GlStateManager.getBoundFramebuffer(); + var oldProjection = new Matrix4f(RenderSystem.getProjectionMatrix()); + GL11C.glViewport(0, 0, this.width, this.height); + + RenderSystem.setProjectionMatrix(new Matrix4f().identity().scale(2,2,-1f).translate(-0.5f, -0.5f, 0.0f), VertexSorter.BY_Z); + + glClearColor(0,0,0,0); + glClearDepth(1); + glBindFramebuffer(GL_FRAMEBUFFER, this.framebuffer.id); + + + RenderSystem.depthMask(true); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + RenderSystem.enableCull(); + RenderSystem.depthFunc(GL_LESS); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + + + if (!state.getFluidState().isEmpty()) { + //TODO: render fluid + } + + var renderLayer = RenderLayers.getBlockLayer(state); + if (renderLayer == RenderLayer.getTranslucent()) { + //TODO: TRANSLUCENT, must sort the quad first + } + + var faces = new ColourDepthTextureData[FACE_VIEWS.size()]; + for (int i = 0; i < faces.length; i++) { + faces[i] = captureView(state, model, FACE_VIEWS.get(i), randomValue); + } + + RenderSystem.setProjectionMatrix(oldProjection, VertexSorter.BY_DISTANCE); + glBindFramebuffer(GL_FRAMEBUFFER, oldFB); + GL11C.glViewport(GlStateManager.Viewport.getX(), GlStateManager.Viewport.getY(), GlStateManager.Viewport.getWidth(), GlStateManager.Viewport.getHeight()); + + return faces; + } + + private ColourDepthTextureData captureView(BlockState state, BakedModel model, MatrixStack stack, long randomValue) { + var vc = Tessellator.getInstance().getBuffer(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + vc.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE); + renderQuads(vc, state, model, stack, randomValue); + BufferRenderer.drawWithGlobalProgram(vc.end()); + + glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); + int[] colourData = new int[this.width*this.height]; + int[] depthData = new int[this.width*this.height]; + glGetTextureImage(this.colourTex.id, 0, GL_RGBA, GL_UNSIGNED_BYTE, colourData); + glGetTextureImage(this.depthTex.id, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, depthData); + return new ColourDepthTextureData(colourData, depthData); + } + + private static void renderQuads(BufferBuilder builder, BlockState state, BakedModel model, MatrixStack stack, long randomValue) { + for (Direction direction : new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, null}) { + var quads = model.getQuads(state, direction, new LocalRandom(randomValue)); + for (var quad : quads) { + builder.quad(stack.peek(), quad, 0, 0, 0, 0, 0); + } + } + } + + public void free() { + this.framebuffer.free(); + this.colourTex.free(); + this.depthTex.free(); + } +} diff --git a/src/main/java/me/cortex/zenith/client/core/model/TextureUtils.java b/src/main/java/me/cortex/zenith/client/core/model/TextureUtils.java new file mode 100644 index 00000000..4d574e6a --- /dev/null +++ b/src/main/java/me/cortex/zenith/client/core/model/TextureUtils.java @@ -0,0 +1,46 @@ +package me.cortex.zenith.client.core.model; + +//Texturing utils to manipulate data from the model bakery +public class TextureUtils { + //Returns if any pixels are not fully transparent or fully translucent + public static boolean hasAlpha(ColourDepthTextureData texture) { + for (int pixel : texture.colour()) { + int alpha = (pixel>>24)&0xFF; + if (alpha != 0 && alpha != 255) { + return true; + } + } + return false; + } + + public static boolean isSolid(ColourDepthTextureData texture) { + for (int pixel : texture.colour()) { + if (((pixel>>24)&0xFF) != 255) { + return false; + } + } + return true; + } + + public static boolean isFullyCovered(ColourDepthTextureData texture) { + for (int pixel : texture.colour()) { + if (((pixel>>24)&0xFF) == 0) { + return false; + } + } + return true; + } + + + public static int computeDepth(ColourDepthTextureData texture, int mode) { + final var colourData = texture.colour(); + final var depthData = texture.depth(); + for (int i = 0; i < colourData.length; i++) { + if ((colourData[0]&0xFF)==0) { + continue; + } + int depth = depthData[0]&0xffffff; + } + return 0; + } +} diff --git a/src/main/java/me/cortex/zenith/client/core/other/BiomeColour.java b/src/main/java/me/cortex/zenith/client/core/other/BiomeColour.java deleted file mode 100644 index 118ca331..00000000 --- a/src/main/java/me/cortex/zenith/client/core/other/BiomeColour.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.cortex.zenith.client.core.other; - -public record BiomeColour(int id, int foliageColour, int waterColour) { -} diff --git a/src/main/java/me/cortex/zenith/client/core/other/BlockStateColour.java b/src/main/java/me/cortex/zenith/client/core/other/BlockStateColour.java deleted file mode 100644 index 12310827..00000000 --- a/src/main/java/me/cortex/zenith/client/core/other/BlockStateColour.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.cortex.zenith.client.core.other; - -public record BlockStateColour(int id, int biomeTintMsk, int[] faceColours) { -} diff --git a/src/main/java/me/cortex/zenith/client/core/other/ColourResolver.java b/src/main/java/me/cortex/zenith/client/core/other/ColourResolver.java deleted file mode 100644 index a3ace29b..00000000 --- a/src/main/java/me/cortex/zenith/client/core/other/ColourResolver.java +++ /dev/null @@ -1,138 +0,0 @@ -package me.cortex.zenith.client.core.other; - -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.texture.NativeImage; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.random.LocalRandom; - -public class ColourResolver { - //TODO: sample from multiple random values and avg it - public static int[] resolveColour(BlockState state) { - return resolveColour(state, 1234567890L); - } - - //The way this works is it takes the and computes its colour, it then computes the area of the quad and the normal direction - // it adds each area and colour to a per direcition colour - // for non specific axis dimensions it takes the normal of each quad computes the dot between it and each of the directions - // and averages that - // if the colour doesnt exist for a specific axis set it to the average of the other axis and or make it translucent - - //TODO: fixme: finish - public static int[] resolveColour(BlockState state, long randomValue) { - if (state == Blocks.AIR.getDefaultState()) { - return new int[6]; - } - int[][] builder = new int[6][5]; - var random = new LocalRandom(randomValue); - if (state.getFluidState().isEmpty()) { - for (Direction direction : new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, null}) { - var quads = MinecraftClient.getInstance() - .getBakedModelManager() - .getBlockModels() - .getModel(state) - .getQuads(state, direction, random); - for (var quad : quads) { - long weightColour = resolveQuadColour(quad); - int colour = (int) weightColour; - int weight = (int) (weightColour>>32); - if (direction == null) { - //TODO: apply normal multiplication to weight - for (int i = 0; i < 6; i++) { - builder[i][0] += weight; - builder[i][4] += weight * ((colour>>>24)&0xFF); - builder[i][3] += weight * ((colour>>>16)&0xFF); - builder[i][2] += weight * ((colour>>>8)&0xFF); - builder[i][1] += weight * ((colour>>>0)&0xFF); - } - } else { - builder[direction.getId()][0] += weight; - builder[direction.getId()][4] += weight*((colour>>>24)&0xFF); - builder[direction.getId()][3] += weight*((colour>>>16)&0xFF); - builder[direction.getId()][2] += weight*((colour>>>8)&0xFF); - builder[direction.getId()][1] += weight*((colour>>>0)&0xFF); - } - } - } - } else { - //TODO FIXME: need to account for both the fluid and block state at the same time - //FIXME: make it not hacky and use the fluid handler thing from fabric - - long weightColour = resolveNI(MinecraftClient.getInstance().getBakedModelManager().getBlockModels().getModelParticleSprite(state).getContents().image); - for (int i = 0; i < 6; i++) { - builder[i][0] = 1; - builder[i][1] += (weightColour>>0)&0xFF; - builder[i][2] += (weightColour>>8)&0xFF; - builder[i][3] += (weightColour>>16)&0xFF; - builder[i][4] += (weightColour>>24)&0xFF; - } - } - - int[] out = new int[6]; - for (int i = 0; i < 6; i++) { - int c = builder[i][0]; - if (c == 0) { - continue; - } - int r = builder[i][4]/c; - int g = builder[i][3]/c; - int b = builder[i][2]/c; - int a = builder[i][1]/c; - out[i] = (r<<24)|(g<<16)|(b<<8)|a; - } - return out; - } - - private static long resolveQuadColour(BakedQuad quad) { - return resolveNI(quad.getSprite().getContents().image); - } - - private static long resolveNI(NativeImage image) { - int r = 0; - int g = 0; - int b = 0; - int a = 0; - int count = 0; - for (int y = 0; y < image.getHeight(); y++) { - for (int x = 0; x < image.getWidth(); x++) { - int colour = image.getColor(x, y); - if (((colour >>> 24)&0xFF) == 0) { - continue; - } - r += (colour >>> 0) & 0xFF; - g += (colour >>> 8) & 0xFF; - b += (colour >>> 16) & 0xFF; - a += (colour >>> 24) & 0xFF; - count++; - } - } - if (count == 0) { - return 0; - } - - r /= count; - g /= count; - b /= count; - a /= count; - - int colour = (r<<24)|(g<<16)|(b<<8)|a; - - return Integer.toUnsignedLong(colour)|(((long)count)<<32); - } - - - public static long resolveBiomeColour(String biomeId) { - var biome = MinecraftClient.getInstance().world.getRegistryManager().get(RegistryKeys.BIOME).get(new Identifier(biomeId)); - if (biome == null) { - System.err.println("Biome: " + biomeId + " doesnt exist in registry!"); - return 0; - } - int ARGBFoliage = biome.getFoliageColor(); - int ARGBWater = biome.getWaterColor(); - return Integer.toUnsignedLong(((ARGBFoliage&0xFFFFFF)<<8)|(ARGBFoliage>>>24)) | (Integer.toUnsignedLong(((ARGBWater&0xFFFFFF)<<8)|(ARGBWater>>>24))<<32); - } -} 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 01b98ed0..91a208d3 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 @@ -4,10 +4,9 @@ package me.cortex.zenith.client.core.rendering; // could maybe tosomething else import me.cortex.zenith.client.core.gl.GlBuffer; +import me.cortex.zenith.client.core.model.ModelManager; import me.cortex.zenith.client.core.rendering.building.BuiltSectionGeometry; import me.cortex.zenith.client.core.rendering.util.UploadStream; -import me.cortex.zenith.client.core.other.BiomeColour; -import me.cortex.zenith.client.core.other.BlockStateColour; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Frustum; @@ -16,7 +15,6 @@ import org.joml.FrustumIntersection; import org.lwjgl.system.MemoryUtil; import java.util.List; -import java.util.concurrent.ConcurrentLinkedDeque; import static org.lwjgl.opengl.ARBMultiDrawIndirect.glMultiDrawElementsIndirect; import static org.lwjgl.opengl.GL30.*; @@ -35,14 +33,9 @@ public abstract class AbstractFarWorldRenderer { protected final GlBuffer uniformBuffer; protected final GeometryManager geometry; - - private final ConcurrentLinkedDeque stateUpdateQueue = new ConcurrentLinkedDeque<>(); - private final ConcurrentLinkedDeque biomeUpdateQueue = new ConcurrentLinkedDeque<>(); - protected final GlBuffer stateDataBuffer; - protected final GlBuffer biomeDataBuffer; + protected final ModelManager models; protected final GlBuffer lightDataBuffer; - //Current camera base level section position protected int sx; protected int sy; @@ -51,12 +44,10 @@ public abstract class AbstractFarWorldRenderer { protected FrustumIntersection frustum; public AbstractFarWorldRenderer(int geometrySize, int maxSections) { - this.uniformBuffer = new GlBuffer(1024, 0); - //TODO: make these both dynamically sized - this.stateDataBuffer = new GlBuffer((1<<16)*28, 0);//Capacity for 1<<16 entries - this.biomeDataBuffer = new GlBuffer(512*4*2, 0);//capacity for 1<<9 entries - this.lightDataBuffer = new GlBuffer(256*4, 0);//256 of uint + 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(); } protected abstract void setupVao(); @@ -89,36 +80,10 @@ public abstract class AbstractFarWorldRenderer { //Upload any new geometry this.geometry.uploadResults(); - - //Upload any block state changes - while (!this.stateUpdateQueue.isEmpty()) { - var stateUpdate = this.stateUpdateQueue.pop(); - long ptr = UploadStream.INSTANCE.upload(this.stateDataBuffer, stateUpdate.id()*28L, 28); - MemoryUtil.memPutInt(ptr, stateUpdate.biomeTintMsk()); ptr+=4; - for (int faceColour : stateUpdate.faceColours()) { - MemoryUtil.memPutInt(ptr, faceColour); ptr+=4; - } - } - - //Upload any biome changes - while (!this.biomeUpdateQueue.isEmpty()) { - var biomeUpdate = this.biomeUpdateQueue.pop(); - long ptr = UploadStream.INSTANCE.upload(this.biomeDataBuffer, biomeUpdate.id()*8L, 8); - MemoryUtil.memPutInt(ptr, biomeUpdate.foliageColour()); ptr+=4; - MemoryUtil.memPutInt(ptr, biomeUpdate.waterColour()); ptr+=4; - } } public abstract void renderFarAwayOpaque(MatrixStack stack, double cx, double cy, double cz); - public void enqueueUpdate(BlockStateColour stateColour) { - this.stateUpdateQueue.add(stateColour); - } - - public void enqueueUpdate(BiomeColour biomeColour) { - this.biomeUpdateQueue.add(biomeColour); - } - public void enqueueResult(BuiltSectionGeometry result) { this.geometry.enqueueResult(result); } @@ -129,10 +94,13 @@ public abstract class AbstractFarWorldRenderer { public void shutdown() { glDeleteVertexArrays(this.vao); + this.models.free(); this.geometry.free(); this.uniformBuffer.free(); - this.stateDataBuffer.free(); - this.biomeDataBuffer.free(); this.lightDataBuffer.free(); } + + public ModelManager getModelManager() { + return this.models; + } } diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/GeometryManager.java b/src/main/java/me/cortex/zenith/client/core/rendering/GeometryManager.java index e9b68c72..07cc84f1 100644 --- a/src/main/java/me/cortex/zenith/client/core/rendering/GeometryManager.java +++ b/src/main/java/me/cortex/zenith/client/core/rendering/GeometryManager.java @@ -43,7 +43,7 @@ public class GeometryManager { public GeometryManager(long geometryBufferSize, int maxSections) { - this.sectionMetaBuffer = new GlBuffer(((long) maxSections) * SECTION_METADATA_SIZE, 0); + this.sectionMetaBuffer = new GlBuffer(((long) maxSections) * SECTION_METADATA_SIZE); this.geometryBuffer = new BufferArena(geometryBufferSize, 8); this.pos2id.defaultReturnValue(-1); } 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 9be5ff4d..5d6ff069 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 @@ -50,10 +50,10 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { public Gl46FarWorldRenderer(int geometryBuffer, int maxSections) { super(geometryBuffer, maxSections); - glCommandBuffer = new GlBuffer(maxSections*5L*4, 0); - glVisibilityBuffer = new GlBuffer(maxSections*4L, 0); - glClearNamedBufferData(glCommandBuffer.id, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, new int[1]); - glClearNamedBufferData(glVisibilityBuffer.id, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, new int[1]); + this.glCommandBuffer = new GlBuffer(maxSections*5L*4); + this.glVisibilityBuffer = new GlBuffer(maxSections*4L); + glClearNamedBufferData(this.glCommandBuffer.id, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, new int[1]); + glClearNamedBufferData(this.glVisibilityBuffer.id, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, new int[1]); setupVao(); } @@ -67,9 +67,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, this.glCommandBuffer.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, this.geometry.metaId()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, this.glVisibilityBuffer.id); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, this.stateDataBuffer.id);//State LUT - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.biomeDataBuffer.id);//Biome LUT - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, this.lightDataBuffer.id);//Lighting LUT + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, this.models.getBufferId()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.lightDataBuffer.id);//Lighting LUT glBindVertexArray(0); } diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/ModelManager.java b/src/main/java/me/cortex/zenith/client/core/rendering/ModelManager.java deleted file mode 100644 index 9525432a..00000000 --- a/src/main/java/me/cortex/zenith/client/core/rendering/ModelManager.java +++ /dev/null @@ -1,5 +0,0 @@ -package me.cortex.zenith.client.core.rendering; - -//Manages the storage and updating of model states, textures and colours -public class ModelManager { -} diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/NvFarWorldRenderer.java b/src/main/java/me/cortex/zenith/client/core/rendering/NvFarWorldRenderer.java deleted file mode 100644 index 0504182a..00000000 --- a/src/main/java/me/cortex/zenith/client/core/rendering/NvFarWorldRenderer.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.cortex.zenith.client.core.rendering; - -import me.cortex.zenith.client.core.gl.shader.Shader; -import me.cortex.zenith.client.core.gl.shader.ShaderType; -import me.cortex.zenith.client.core.rendering.util.UploadStream; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.util.math.MatrixStack; - -import static org.lwjgl.opengl.ARBMultiDrawIndirect.glMultiDrawElementsIndirect; -import static org.lwjgl.opengl.GL30.glBindVertexArray; -import static org.lwjgl.opengl.NVMeshShader.glDrawMeshTasksNV; - -//TODO: make this a 2 phase culling system -// first phase renders the terrain, in the terrain task shader it also checks if the section was not visible in the frustum but now is -// and then renders it and marks it as being in the frustum -public class NvFarWorldRenderer extends AbstractFarWorldRenderer { - private final Shader primaryTerrainRaster = Shader.make() - .add(ShaderType.TASK, "voxelmon:lod/nvmesh/primary.task") - .add(ShaderType.MESH, "voxelmon:lod/nvmesh/primary.mesh") - .add(ShaderType.FRAGMENT, "voxelmon:lod/nvmesh/primary.frag") - .compile(); - - public NvFarWorldRenderer(int geometrySize, int maxSections) { - super(geometrySize, maxSections); - } - - @Override - protected void setupVao() { - - } - - @Override - public void renderFarAwayOpaque(MatrixStack stack, double cx, double cy, double cz) { - if (this.geometry.getSectionCount() == 0) { - return; - } - RenderLayer.getCutoutMipped().startDrawing(); - - UploadStream.INSTANCE.commit(); - - glBindVertexArray(this.vao); - this.primaryTerrainRaster.bind(); - glDrawMeshTasksNV(0, this.geometry.getSectionCount()); - glBindVertexArray(0); - - - RenderLayer.getCutoutMipped().endDrawing(); - } - - @Override - public void shutdown() { - super.shutdown(); - - } -} diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/SharedIndexBuffer.java b/src/main/java/me/cortex/zenith/client/core/rendering/SharedIndexBuffer.java index f3c07a07..201b0d2c 100644 --- a/src/main/java/me/cortex/zenith/client/core/rendering/SharedIndexBuffer.java +++ b/src/main/java/me/cortex/zenith/client/core/rendering/SharedIndexBuffer.java @@ -14,7 +14,7 @@ public class SharedIndexBuffer { private final GlBuffer indexBuffer; public SharedIndexBuffer() { - this.indexBuffer = new GlBuffer((1<<16)*6*2 + 6*2*3, 0); + this.indexBuffer = new GlBuffer((1<<16)*6*2 + 6*2*3); var quadIndexBuff = IndexUtil.generateQuadIndicesShort(16380); var cubeBuff = generateCubeIndexBuffer(); diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/util/BufferArena.java b/src/main/java/me/cortex/zenith/client/core/rendering/util/BufferArena.java index 6f31f977..d03c1c71 100644 --- a/src/main/java/me/cortex/zenith/client/core/rendering/util/BufferArena.java +++ b/src/main/java/me/cortex/zenith/client/core/rendering/util/BufferArena.java @@ -18,7 +18,7 @@ public class BufferArena { } this.size = capacity; this.elementSize = elementSize; - this.buffer = new GlBuffer(capacity, 0); + this.buffer = new GlBuffer(capacity); this.allocationMap.setLimit(capacity/elementSize); } diff --git a/src/main/java/me/cortex/zenith/client/core/util/DebugUtil.java b/src/main/java/me/cortex/zenith/client/core/util/DebugUtil.java index 30d3bfef..751c0554 100644 --- a/src/main/java/me/cortex/zenith/client/core/util/DebugUtil.java +++ b/src/main/java/me/cortex/zenith/client/core/util/DebugUtil.java @@ -7,7 +7,7 @@ import net.minecraft.util.math.Box; import org.joml.Matrix4f; public class DebugUtil { - private static Matrix4f positionMatrix = new Matrix4f().identity(); + public static Matrix4f positionMatrix = new Matrix4f().identity(); public static void setPositionMatrix(MatrixStack stack) { positionMatrix = new Matrix4f(stack.peek().getPositionMatrix()); } 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 4bf335e5..fdbd7d43 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl @@ -11,16 +11,10 @@ layout(binding = 0, std140) uniform SceneUniform { uint frameId; }; -struct State { - uint biomeTintMsk; +struct BlockModel { uint faceColours[6]; }; -struct Biome { - uint foliage; - uint water; -}; - struct SectionMeta { uvec4 header; uvec4 drawdata; @@ -57,15 +51,11 @@ layout(binding = 4, std430) VISIBILITY_ACCESS restrict buffer VisibilityBuffer { uint visibilityData[]; }; -layout(binding = 5, std430) readonly restrict buffer StateBuffer { - State stateData[]; +layout(binding = 5, std430) readonly restrict buffer ModelBuffer { + BlockModel modelData[]; }; -layout(binding = 6, std430) readonly restrict buffer BiomeBuffer { - Biome biomeData[]; -}; - -layout(binding = 7, std430) readonly restrict buffer LightingBuffer { +layout(binding = 6, std430) readonly restrict buffer LightingBuffer { uint lightData[]; }; 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 22c061a2..1c815da5 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert @@ -63,20 +63,11 @@ void main() { uint stateId = extractStateId(quad); uint biomeId = extractBiomeId(quad); - State stateInfo = stateData[stateId]; + BlockModel stateInfo = modelData[stateId]; colour = uint2vec4RGBA(stateInfo.faceColours[face]); colour *= getLighting(extractLightId(quad)); - if (((stateInfo.biomeTintMsk>>face)&1) == 1) { - vec4 biomeColour = uint2vec4RGBA(biomeData[biomeId].foliage); - colour *= biomeColour; - } - //Apply water tint - if (((stateInfo.biomeTintMsk>>6)&1) == 1) { - colour *= vec4(0.247, 0.463, 0.894, 1); - } - //Apply face tint if (face == 0) { colour.xyz *= vec3(0.75, 0.75, 0.75);