From d499a19d4eef9112d8b62eb0e5862bae55dbc972 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:50:46 +1000 Subject: [PATCH] Added alpha discard flag to faces --- .../client/core/model/ModelManager.java | 37 ++++++++++++++----- .../rendering/AbstractFarWorldRenderer.java | 2 +- .../core/rendering/Gl46FarWorldRenderer.java | 1 + .../zenith/shaders/lod/gl46/bindings.glsl | 3 +- .../zenith/shaders/lod/gl46/block_model.glsl | 4 ++ .../assets/zenith/shaders/lod/gl46/quads.frag | 2 +- .../assets/zenith/shaders/lod/gl46/quads.vert | 17 +++++---- 7 files changed, 46 insertions(+), 20 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 a9fe5e84..d6fa3119 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 @@ -160,25 +160,29 @@ public class ModelManager { long uploadPtr = UploadStream.INSTANCE.upload(this.modelBuffer, (long) modelId * MODEL_SIZE, MODEL_SIZE); - //TODO: implement + //TODO: implement; + // TODO: if it has a constant colour instead... idk why (apparently for things like spruce leaves)?? but premultiply the texture data by the constant colour boolean hasBiomeColourResolver = false; + + //TODO: special case stuff like vines and glow lichen, where it can be represented by a single double sided quad + // since that would help alot with perf of lots of vines, can be done by having one of the faces just not exist and the other be in no occlusion mode + + var sizes = this.computeModelDepth(textureData, checkMode); + //TODO: THIS, note this can be tested for in 2 ways, re render the model with quad culling disabled and see if the result // is the same, (if yes then needs double sided quads) // another way to test it is if e.g. up and down havent got anything rendered but the sides do (e.g. all plants etc) - boolean needsDoubleSidedQuads = false; - - //TODO: special case stuff like vines and glow lichen, where it can be represented by a single double sided quad - // since that would help alot with perf of lots of vines + boolean needsDoubleSidedQuads = (sizes[0] < -0.1 && sizes[1] < -0.1) || (sizes[2] < -0.1 && sizes[3] < -0.1) || (sizes[4] < -0.1 && sizes[5] < -0.1); - //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); //Each face gets 1 byte, with the top 2 bytes being for whatever - long metadata = hasBiomeColourResolver?1:0; + long metadata = 0; + metadata |= hasBiomeColourResolver?1:0; metadata |= blockRenderLayer == RenderLayer.getTranslucent()?2:0; + metadata |= needsDoubleSidedQuads?4: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 @@ -192,6 +196,7 @@ public class ModelManager { continue; } var faceSize = TextureUtils.computeBounds(textureData[face], checkMode); + int writeCount = TextureUtils.getWrittenPixelCount(textureData[face], checkMode); boolean faceCoversFullBlock = faceSize[0] == 0 && faceSize[2] == 0 && faceSize[1] == (this.modelTextureSize-1) && faceSize[3] == (this.modelTextureSize-1); @@ -206,7 +211,6 @@ public class ModelManager { 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; @@ -231,6 +235,14 @@ public class ModelManager { faceModelData |= Math.round(offset*63)<<16;//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 + //Stuff like fences are solid, however they have extra side piece that mean it needs to have discard on + int area = (faceSize[1]-faceSize[0]+1) * (faceSize[3]-faceSize[2]+1); + boolean needsAlphaDiscard = ((float)writeCount)/area<0.9;//If the amount of area covered by written pixels is less than a threashold, disable discard as its not needed + + needsAlphaDiscard |= blockRenderLayer != RenderLayer.getSolid(); + + faceModelData |= needsAlphaDiscard?1<<22:0; + MemoryUtil.memPutInt(faceUploadPtr, faceModelData); } this.metadataCache[modelId] = metadata; @@ -238,6 +250,9 @@ public class ModelManager { 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 + int modelFlags = 0; + //modelFlags |= blockRenderLayer == RenderLayer.getSolid()?0:1;// should discard alpha + MemoryUtil.memPutInt(uploadPtr, modelFlags); @@ -344,4 +359,8 @@ public class ModelManager { this.textures.free(); glDeleteSamplers(this.blockSampler); } + + public void addDebugInfo(List info) { + + } } 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 e3146be5..9c634147 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 @@ -90,7 +90,7 @@ public abstract class AbstractFarWorldRenderer { } public void addDebugData(List debug) { - + this.models.addDebugInfo(debug); } public void shutdown() { 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 f2e4c127..16745612 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 @@ -177,6 +177,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer { @Override public void addDebugData(List debug) { + super.addDebugData(debug); debug.add("Geometry buffer usage: " + ((float)Math.round((this.geometry.getGeometryBufferUsage()*100000))/1000) + "%"); debug.add("Render Sections: " + this.geometry.getSectionCount()); } 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 e923999b..97cafa50 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/bindings.glsl @@ -13,7 +13,8 @@ layout(binding = 0, std140) uniform SceneUniform { struct BlockModel { uint faceData[6]; - uint _pad[10]; + uint flagsA; + uint _pad[9]; }; struct SectionMeta { 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 0c2588c7..9a8198e4 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 @@ -6,4 +6,8 @@ float extractFaceIndentation(uint faceData) { vec4 extractFaceSizes(uint faceData) { return (vec4(faceData&0xF, (faceData>>4)&0xF, (faceData>>8)&0xF, (faceData>>12)&0xF)/16)+vec4(0,1f/16,0,1f/16); +} + +uint faceHasAlphaCuttout(uint faceData) { + return (faceData>>22)&1; } \ No newline at end of file diff --git a/src/main/resources/assets/zenith/shaders/lod/gl46/quads.frag b/src/main/resources/assets/zenith/shaders/lod/gl46/quads.frag index 0f7db1de..208cbb02 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/quads.frag +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/quads.frag @@ -4,7 +4,7 @@ layout(binding = 0) uniform sampler2D blockModelAtlas; layout(location = 0) in vec2 uv; layout(location = 1) in flat vec2 baseUV; layout(location = 2) in flat vec4 colourTinting; -layout(location = 3) in flat int discardAlpha; +layout(location = 3) in flat uint discardAlpha; layout(location = 0) out vec4 outColour; void main() { 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 297021ed..1eebdb24 100644 --- a/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert +++ b/src/main/resources/assets/zenith/shaders/lod/gl46/quads.vert @@ -9,7 +9,7 @@ layout(location = 0) out vec2 uv; layout(location = 1) out flat vec2 baseUV; layout(location = 2) out flat vec4 colourTinting; -layout(location = 3) out flat int discardAlpha; +layout(location = 3) out flat uint discardAlpha; uint extractLodLevel() { return uint(gl_BaseInstance)>>29; @@ -26,13 +26,13 @@ vec4 uint2vec4RGBA(uint colour) { } //Gets the face offset with respect to the face direction (e.g. some will be + some will be -) -float getDepthOffset(BlockModel model, uint face) { - float offset = extractFaceIndentation(model.faceData[face]); +float getDepthOffset(uint faceData, uint face) { + float offset = extractFaceIndentation(faceData); return offset * (1-((int(face)&1)*2)); } -vec2 getFaceSizeOffset(BlockModel model, uint face, uint corner) { - vec4 faceOffsetsSizes = extractFaceSizes(model.faceData[face]); +vec2 getFaceSizeOffset(uint faceData, uint corner) { + vec4 faceOffsetsSizes = extractFaceSizes(faceData); return mix(faceOffsetsSizes.xz, -(1-faceOffsetsSizes.yw), bvec2(((corner>>1)&1)==1, (corner&1)==1)); } @@ -46,6 +46,7 @@ void main() { uint face = extractFace(quad); uint modelId = extractStateId(quad); BlockModel model = modelData[modelId]; + uint faceData = model.faceData[face]; //Change the ordering due to backface culling //NOTE: when rendering, backface culling is disabled as we simply dispatch calls for each face @@ -58,11 +59,11 @@ void main() { ivec3 lodCorner = ((extractRelativeLodPos()<>1)&1, cornerIdx&1)); vec2 size = (quadSize + faceOffset) * (1<>1) == 0) {//Up/down offset = offset.xzy; @@ -85,7 +86,7 @@ void main() { baseUV = modelUV + (vec2(face%3, face/3) * (1f/(vec2(3,2)*256f))); uv = quadSize + faceOffset;//Add in the face offset for 0,0 uv - discardAlpha = 0; + discardAlpha = faceHasAlphaCuttout(faceData); //Compute lighting colourTinting = getLighting(extractLightId(quad));