Added alpha discard flag to faces
This commit is contained in:
@@ -160,25 +160,29 @@ public class ModelManager {
|
|||||||
long uploadPtr = UploadStream.INSTANCE.upload(this.modelBuffer, (long) modelId * MODEL_SIZE, MODEL_SIZE);
|
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;
|
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
|
//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)
|
// 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)
|
// 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;
|
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);
|
||||||
|
|
||||||
//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
|
|
||||||
|
|
||||||
|
|
||||||
//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
|
//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 |= 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
|
//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
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
var faceSize = TextureUtils.computeBounds(textureData[face], checkMode);
|
var faceSize = TextureUtils.computeBounds(textureData[face], checkMode);
|
||||||
|
int writeCount = TextureUtils.getWrittenPixelCount(textureData[face], checkMode);
|
||||||
|
|
||||||
boolean faceCoversFullBlock = faceSize[0] == 0 && faceSize[2] == 0 &&
|
boolean faceCoversFullBlock = faceSize[0] == 0 && faceSize[2] == 0 &&
|
||||||
faceSize[1] == (this.modelTextureSize-1) && faceSize[3] == (this.modelTextureSize-1);
|
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
|
occludesFace &= offset < 0.1;//If the face is rendered far away from the other face, then it doesnt occlude
|
||||||
|
|
||||||
if (occludesFace) {
|
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
|
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;
|
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
|
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
|
//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);
|
MemoryUtil.memPutInt(faceUploadPtr, faceModelData);
|
||||||
}
|
}
|
||||||
this.metadataCache[modelId] = metadata;
|
this.metadataCache[modelId] = metadata;
|
||||||
@@ -238,6 +250,9 @@ public class ModelManager {
|
|||||||
uploadPtr += 4*6;
|
uploadPtr += 4*6;
|
||||||
//Have 40 bytes free for remaining model data
|
//Have 40 bytes free for remaining model data
|
||||||
// todo: put in like the render layer type ig? along with colour resolver info
|
// 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();
|
this.textures.free();
|
||||||
glDeleteSamplers(this.blockSampler);
|
glDeleteSamplers(this.blockSampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDebugInfo(List<String> info) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public abstract class AbstractFarWorldRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addDebugData(List<String> debug) {
|
public void addDebugData(List<String> debug) {
|
||||||
|
this.models.addDebugInfo(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDebugData(List<String> debug) {
|
public void addDebugData(List<String> debug) {
|
||||||
|
super.addDebugData(debug);
|
||||||
debug.add("Geometry buffer usage: " + ((float)Math.round((this.geometry.getGeometryBufferUsage()*100000))/1000) + "%");
|
debug.add("Geometry buffer usage: " + ((float)Math.round((this.geometry.getGeometryBufferUsage()*100000))/1000) + "%");
|
||||||
debug.add("Render Sections: " + this.geometry.getSectionCount());
|
debug.add("Render Sections: " + this.geometry.getSectionCount());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ layout(binding = 0, std140) uniform SceneUniform {
|
|||||||
|
|
||||||
struct BlockModel {
|
struct BlockModel {
|
||||||
uint faceData[6];
|
uint faceData[6];
|
||||||
uint _pad[10];
|
uint flagsA;
|
||||||
|
uint _pad[9];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SectionMeta {
|
struct SectionMeta {
|
||||||
|
|||||||
@@ -7,3 +7,7 @@ float extractFaceIndentation(uint faceData) {
|
|||||||
vec4 extractFaceSizes(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);
|
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;
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ layout(binding = 0) uniform sampler2D blockModelAtlas;
|
|||||||
layout(location = 0) in vec2 uv;
|
layout(location = 0) in vec2 uv;
|
||||||
layout(location = 1) in flat vec2 baseUV;
|
layout(location = 1) in flat vec2 baseUV;
|
||||||
layout(location = 2) in flat vec4 colourTinting;
|
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;
|
layout(location = 0) out vec4 outColour;
|
||||||
void main() {
|
void main() {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
layout(location = 0) out vec2 uv;
|
layout(location = 0) out vec2 uv;
|
||||||
layout(location = 1) out flat vec2 baseUV;
|
layout(location = 1) out flat vec2 baseUV;
|
||||||
layout(location = 2) out flat vec4 colourTinting;
|
layout(location = 2) out flat vec4 colourTinting;
|
||||||
layout(location = 3) out flat int discardAlpha;
|
layout(location = 3) out flat uint discardAlpha;
|
||||||
|
|
||||||
uint extractLodLevel() {
|
uint extractLodLevel() {
|
||||||
return uint(gl_BaseInstance)>>29;
|
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 -)
|
//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 getDepthOffset(uint faceData, uint face) {
|
||||||
float offset = extractFaceIndentation(model.faceData[face]);
|
float offset = extractFaceIndentation(faceData);
|
||||||
return offset * (1-((int(face)&1)*2));
|
return offset * (1-((int(face)&1)*2));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 getFaceSizeOffset(BlockModel model, uint face, uint corner) {
|
vec2 getFaceSizeOffset(uint faceData, uint corner) {
|
||||||
vec4 faceOffsetsSizes = extractFaceSizes(model.faceData[face]);
|
vec4 faceOffsetsSizes = extractFaceSizes(faceData);
|
||||||
return mix(faceOffsetsSizes.xz, -(1-faceOffsetsSizes.yw), bvec2(((corner>>1)&1)==1, (corner&1)==1));
|
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 face = extractFace(quad);
|
||||||
uint modelId = extractStateId(quad);
|
uint modelId = extractStateId(quad);
|
||||||
BlockModel model = modelData[modelId];
|
BlockModel model = modelData[modelId];
|
||||||
|
uint faceData = model.faceData[face];
|
||||||
|
|
||||||
//Change the ordering due to backface culling
|
//Change the ordering due to backface culling
|
||||||
//NOTE: when rendering, backface culling is disabled as we simply dispatch calls for each face
|
//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;
|
ivec3 lodCorner = ((extractRelativeLodPos()<<lodLevel) - (baseSectionPos&(ivec3((1<<lodLevel)-1))))<<5;
|
||||||
vec3 corner = innerPos * (1<<lodLevel) + lodCorner;
|
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 quadSize = vec2(extractSize(quad) * ivec2((cornerIdx>>1)&1, cornerIdx&1));
|
||||||
vec2 size = (quadSize + faceOffset) * (1<<lodLevel);
|
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
|
if ((face>>1) == 0) {//Up/down
|
||||||
offset = offset.xzy;
|
offset = offset.xzy;
|
||||||
@@ -85,7 +86,7 @@ void main() {
|
|||||||
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 = quadSize + faceOffset;//Add in the face offset for 0,0 uv
|
uv = quadSize + faceOffset;//Add in the face offset for 0,0 uv
|
||||||
|
|
||||||
discardAlpha = 0;
|
discardAlpha = faceHasAlphaCuttout(faceData);
|
||||||
|
|
||||||
//Compute lighting
|
//Compute lighting
|
||||||
colourTinting = getLighting(extractLightId(quad));
|
colourTinting = getLighting(extractLightId(quad));
|
||||||
|
|||||||
Reference in New Issue
Block a user