Added alpha discard flag to faces

This commit is contained in:
mcrcortex
2024-01-29 11:50:46 +10:00
parent 6302d3db1e
commit d499a19d4e
7 changed files with 46 additions and 20 deletions

View File

@@ -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<String> info) {
}
}

View File

@@ -90,7 +90,7 @@ public abstract class AbstractFarWorldRenderer {
}
public void addDebugData(List<String> debug) {
this.models.addDebugInfo(debug);
}
public void shutdown() {

View File

@@ -177,6 +177,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
@Override
public void addDebugData(List<String> debug) {
super.addDebugData(debug);
debug.add("Geometry buffer usage: " + ((float)Math.round((this.geometry.getGeometryBufferUsage()*100000))/1000) + "%");
debug.add("Render Sections: " + this.geometry.getSectionCount());
}

View File

@@ -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 {

View File

@@ -7,3 +7,7 @@ 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;
}

View File

@@ -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() {

View File

@@ -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()<<lodLevel) - (baseSectionPos&(ivec3((1<<lodLevel)-1))))<<5;
vec3 corner = innerPos * (1<<lodLevel) + lodCorner;
vec2 faceOffset = getFaceSizeOffset(model, face, cornerIdx);
vec2 faceOffset = getFaceSizeOffset(faceData, cornerIdx);
vec2 quadSize = vec2(extractSize(quad) * ivec2((cornerIdx>>1)&1, cornerIdx&1));
vec2 size = (quadSize + faceOffset) * (1<<lodLevel);
vec3 offset = vec3(size, (float(face&1) + getDepthOffset(model, face)) * (1<<lodLevel));
vec3 offset = vec3(size, (float(face&1) + getDepthOffset(faceData, face)) * (1<<lodLevel));
if ((face>>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));