From 2e5eca6f24849d717e80b4ee8d6ede90cb67a1a3 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Sun, 28 Jan 2024 15:13:04 +1000 Subject: [PATCH] Mostly finished Model data i think --- .../client/core/model/ModelManager.java | 61 ++++++++++++++++--- .../client/core/model/TextureUtils.java | 24 ++------ .../core/rendering/GeometryManager.java | 16 ++--- .../core/rendering/Gl46FarWorldRenderer.java | 3 - .../rendering/building/RenderDataFactory.java | 8 ++- 5 files changed, 74 insertions(+), 38 deletions(-) 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 ab021137..8356bc34 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 @@ -5,12 +5,14 @@ import com.mojang.blaze3d.platform.GlStateManager; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import me.cortex.zenith.client.core.gl.GlBuffer; import me.cortex.zenith.client.core.gl.GlTexture; +import me.cortex.zenith.client.core.rendering.util.UploadStream; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayers; import net.minecraft.registry.Registries; import net.minecraft.util.math.Direction; +import org.lwjgl.system.MemoryUtil; import java.util.ArrayList; import java.util.Arrays; @@ -155,23 +157,68 @@ public class ModelManager { // solid layer renders it as black so might need to add a bitset in the model data of whether the face is rendering // in discard or solid mode maybe? + long uploadPtr = UploadStream.INSTANCE.upload(this.modelBuffer, (long) modelId * MODEL_SIZE, MODEL_SIZE); + //TODO: implement + boolean hasBiomeColourResolver = false; + //This also checks if there is a block colour resolver for the given blockstate and marks that the block has a resolver var sizes = this.computeModelDepth(textureData, checkMode); - for (int face = 0; face < 6; face++) { - if (sizes[face] < -0.1) {//Face is empty, so ignore + //Each face gets 1 byte, with the top 2 bytes being for whatever + long metadata = hasBiomeColourResolver?1:0; + metadata |= blockRenderLayer == RenderLayer.getTranslucent()?2:0; + + //TODO: add a bunch of control config options for overriding/setting options of metadata for each face of each type + for (int face = 5; face != -1; face--) {//In reverse order to make indexing into the metadata long easier + long faceUploadPtr = uploadPtr + 4L * face;//Each face gets 4 bytes worth of data + metadata <<= 8; + float offset = sizes[face]; + if (offset < -0.1) {//Face is empty, so ignore + metadata |= 0xFF;//Mark the face as non-existent + //Set to -1 as safepoint + MemoryUtil.memPutLong(faceUploadPtr, -1); continue; } - //TODO: replace this with a more intelligent method that - // if using solid use TextureUtils.computeBounds() with depth testing - // if using translucent or transparent compare if alpha is 0 var faceSize = TextureUtils.computeBounds(textureData[face], checkMode); - int eee = 0; - } + boolean faceCoversFullBlock = faceSize[0] == 0 && faceSize[2] == 0 && + faceSize[1] == (this.modelTextureSize-1) && faceSize[3] == (this.modelTextureSize-1); + metadata |= faceCoversFullBlock?2:0; + + //TODO: add alot of config options for the following + boolean occludesFace = true; + occludesFace &= blockRenderLayer != RenderLayer.getTranslucent();//If its translucent, it doesnt occlude + + //TODO: make this an option, basicly if the face is really close, it occludes otherwise it doesnt + occludesFace &= offset < 0.1;//If the face is rendered far away from the other face, then it doesnt occlude + + if (occludesFace) { + int writeCount = TextureUtils.getWrittenPixelCount(textureData[face], checkMode); + occludesFace &= ((float)writeCount)/(this.modelTextureSize * this.modelTextureSize) > 0.9;// only occlude if the face covers more than 90% of the face + } + metadata |= occludesFace?1:0; + + + //Scale face size from 0->this.modelTextureSize-1 to 0->15 + for (int i = 0; i < 4; i++) { + faceSize[i] = Math.round((((float)faceSize[i])/(this.modelTextureSize-1))*15); + } + + int faceModelData = 0; + faceModelData |= faceSize[0] | (faceSize[1]<<4) | (faceSize[2]<<8) | (faceSize[3]<<12); + faceModelData |= Math.round(offset*63);//Change the scale from 0->1 (ends inclusive) float to 0->63 (6 bits) NOTE! that 63 == 1.0f meaning its shifted all the way to the other side of the model + //Still have 11 bits free + + MemoryUtil.memPutInt(faceUploadPtr, faceModelData); + } + this.metadataCache[modelId] = metadata; + + uploadPtr += 4*6; + //Have 40 bytes free for remaining model data + // todo: put in like the render layer type ig? along with colour resolver info 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 index c72358fb..2c828379 100644 --- a/src/main/java/me/cortex/zenith/client/core/model/TextureUtils.java +++ b/src/main/java/me/cortex/zenith/client/core/model/TextureUtils.java @@ -4,25 +4,11 @@ import java.util.Map; //Texturing utils to manipulate data from the model bakery public class TextureUtils { - //Returns a bitset of - public static int computeColourData(ColourDepthTextureData texture) { - final var colour = texture.colour(); - int bitset = 0b101; - for (int i = 0; i < colour.length && bitset != 0b010; i++) { - int pixel = colour[i]; - int alpha = (pixel>>24)&0xFF; - bitset |= (alpha != 0 && alpha != 255)?2:0;//Test if the pixel is translucent (has alpha) - bitset &= (alpha != 0)?3:7;// test if the pixel is not empty (assumes that if alpha is 0 it wasnt written to!!) FIXME: THIS MIGHT NOT BE CORRECT - bitset &= alpha != 255?6:7;// test if the pixel is anything but solid, (occlusion culling stuff) - } - return bitset; - } - //Returns the number of non pixels not written to - public static int getNonWrittenPixels(ColourDepthTextureData texture) { + public static int getWrittenPixelCount(ColourDepthTextureData texture, int checkMode) { int count = 0; - for (int pixel : texture.depth()) { - count += ((pixel&0xFF) == 0)?1:0; + for (int i = 0; i < texture.colour().length; i++) { + count += wasPixelWritten(texture, checkMode, i)?1:0; } return count; } @@ -140,7 +126,7 @@ public class TextureUtils { } maxX--; } while (maxX != -1); - maxX++; + //maxX++; //Compute y bounds @@ -168,7 +154,7 @@ public class TextureUtils { } maxY--; } while (maxY != -1); - maxY++; + //maxY++; return new int[]{minX, maxX, minY, maxY}; } 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 67d84435..ecfdbd00 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 @@ -142,18 +142,19 @@ public class GeometryManager { //TODO: pack the offsets of each axis so that implicit face culling can work //Note! the opaquePreDataCount and translucentPreDataCount are never writen to the meta buffer, as they are indexed in reverse relative to the base opaque and translucent geometry - private record SectionMeta(long position, int aabb, int opaqueGeometryPtr, int opaqueQuadCount, int opaquePreDataCount, int translucentGeometryPtr, int translucentQuadCount, int translucentPreDataCount) { + private record SectionMeta(long position, int aabb, int opaqueGeometryPtr, int count, int translucentGeometryPtr) { public void writeMetadata(long ptr) { //THIS IS DUE TO ENDIANNESS and that we are splitting a long into 2 ints MemoryUtil.memPutInt(ptr, (int) (this.position>>32)); ptr += 4; MemoryUtil.memPutInt(ptr, (int) this.position); ptr += 4; - ptr += 8; + MemoryUtil.memPutInt(ptr, (int) this.aabb); ptr += 4; + ptr += 4; - MemoryUtil.memPutInt(ptr, (int) this.opaqueGeometryPtr + this.opaquePreDataCount); ptr += 4; - MemoryUtil.memPutInt(ptr, this.opaqueQuadCount); ptr += 4; + MemoryUtil.memPutInt(ptr, this.count); ptr += 4; + //MemoryUtil.memPutInt(ptr, this.opaqueQuadCount); ptr += 4; - MemoryUtil.memPutInt(ptr, (int) this.translucentGeometryPtr + this.translucentPreDataCount); ptr += 4; - MemoryUtil.memPutInt(ptr, this.translucentQuadCount); ptr += 4; + //MemoryUtil.memPutInt(ptr, (int) this.translucentGeometryPtr + this.translucentPreDataCount); ptr += 4; + //MemoryUtil.memPutInt(ptr, this.translucentQuadCount); ptr += 4; } } @@ -161,7 +162,8 @@ public class GeometryManager { int geometryPtr = (int) this.geometryBuffer.upload(geometry.opaque.buffer()); //TODO: support translucent geometry - return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0, -1,0, 0); + //return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0, -1,0, 0); + return new SectionMeta(geometry.position, 0, geometryPtr, (int) (geometry.opaque.buffer().size/8), 0); } private void freeMeta(SectionMeta meta) { 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 ec1cc68c..85de7dc8 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 @@ -78,9 +78,6 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { } public void renderFarAwayOpaque(MatrixStack stack, double cx, double cy, double cz) { - this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.OAK_BUTTON.getDefaultState().with(WallMountedBlock.FACE, BlockFace.FLOOR).with(WallMountedBlock.FACING, Direction.SOUTH)); - //this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE.getDefaultState()); - //this.getModelManager().addEntry(this.frameId%(1<<15), Blocks.COMPARATOR.getDefaultState()); if (this.geometry.getSectionCount() == 0) { return; } diff --git a/src/main/java/me/cortex/zenith/client/core/rendering/building/RenderDataFactory.java b/src/main/java/me/cortex/zenith/client/core/rendering/building/RenderDataFactory.java index 8b7564e5..78a66133 100644 --- a/src/main/java/me/cortex/zenith/client/core/rendering/building/RenderDataFactory.java +++ b/src/main/java/me/cortex/zenith/client/core/rendering/building/RenderDataFactory.java @@ -29,9 +29,13 @@ public class RenderDataFactory { public BuiltSection generateMesh(WorldSection section, int buildMask) { section.copyDataTo(this.sectionCache); - var output = new MemoryBuffer(8*1); + //TODO:NOTE! when doing face culling of translucent blocks, + // if the connecting type of the translucent block is the same AND the face is full, discard it + // this stops e.g. multiple layers of glass (and ocean) from having 3000 layers of quads etc - return new BuiltSection(section.getKey(), new BuiltSectionGeometry(output, new short[0]), null); + var buff = new MemoryBuffer(8*1); + + return new BuiltSection(section.getKey(), new BuiltSectionGeometry(buff, new short[0]), null); } }