abstract and pull out vertex shader internals

This commit is contained in:
mcrcortex
2025-10-11 23:50:45 +10:00
parent c9eddb2cbb
commit dbac73048f
5 changed files with 250 additions and 10 deletions

View File

@@ -95,7 +95,7 @@ public class MDICSectionRenderer extends AbstractSectionRenderer<MDICViewport, B
this.pipeline = pipeline;
//The pipeline can be used to transform the renderer in abstract ways
String vertex = ShaderLoader.parse("voxy:lod/gl46/quads2.vert");
String vertex = ShaderLoader.parse("voxy:lod/gl46/quads3.vert");
String taa = pipeline.taaFunction("taaShift");
if (taa != null) {
vertex += "\n"+taa;//inject it at the end

View File

@@ -11,8 +11,8 @@ layout(binding = 2) uniform sampler2D depthTex;
//TODO: need to fix when merged quads have discardAlpha set to false but they span multiple tiles
// however they are not a full block
layout(location = 0) in vec2 uv;
layout(location = 1) in flat uvec4 interData;
layout(location = 0) in flat uvec4 interData;
layout(location = 1) in vec2 uv;
#ifdef DEBUG_RENDER
layout(location = 7) in flat uint quadDebug;
@@ -48,11 +48,7 @@ bool useCutout() {
}
uint getFace() {
#ifndef PATCHED_SHADER
return (interData.w>>8)&7u;
#else
return (interData.y>>8)&7u;
#endif
return (interData.x>>4)&7u;
}
#ifdef PATCHED_SHADER

View File

@@ -14,8 +14,8 @@
//#define DEBUG_RENDER
layout(location = 0) out vec2 uv;
layout(location = 1) out flat uvec4 interData;
layout(location = 0) out flat uvec4 interData;
layout(location = 1) out vec2 uv;
uint packVec4(vec4 vec) {
uvec4 vec_=uvec4(vec*255)<<uvec4(24,16,8,0);

View File

@@ -0,0 +1,55 @@
#version 460 core
#extension GL_ARB_gpu_shader_int64 : enable
#define QUAD_BUFFER_BINDING 1
#define MODEL_BUFFER_BINDING 3
#define MODEL_COLOUR_BUFFER_BINDING 4
#define POSITION_SCRATCH_BINDING 5
#define LIGHTING_SAMPLER_BINDING 1
#define USE_INTERPOLATED_UV
#import <voxy:lod/quad_format.glsl>
#import <voxy:lod/block_model.glsl>
#import <voxy:lod/gl46/bindings.glsl>
#import <voxy:lod/quad_util.glsl>
layout(location = 0) out flat uvec4 interData;
#ifdef USE_INTERPOLATED_UV
layout(location = 1) out vec2 uv;
#endif
#ifdef DEBUG_RENDER
layout(location = 7) out flat uint quadDebug;
#endif
vec2 taaShift();
//TODO: add a mechanism so that some quads can ignore backface culling
// this would help alot with stuff like crops as they would look kinda weird i think,
// same with flowers etc
void main() {
taaOffset = taaShift();
QuadData quad;
setupQuad(quad, quadData[uint(gl_VertexID)>>2], positionBuffer[gl_BaseInstance], (gl_VertexID&3) == 1);
uint cornerId = gl_VertexID&3;
gl_Position = getQuadCornerPos(quad, cornerId);
#ifdef USE_INTERPOLATED_UV
uv = getCornerUV(quad, cornerId);
#endif
//Note: other data is automatically discarded as it is undefiend and has not been generated
interData = quad.attributeData;
#ifdef DEBUG_RENDER
quadDebug = extractDetail(positionBuffer[gl_BaseInstance]);
#endif
}
#ifndef TAA_PATCH
vec2 taaShift() {return vec2(0.0);}
#endif

View File

@@ -0,0 +1,189 @@
//Common utility functions for decoding and operating on quads
vec3 swizzelDataAxis(uint axis, vec3 data) {
return mix(mix(data.zxy,data.xzy,bvec3(axis==0)),data,bvec3(axis==1));
}
uint extractDetail(uvec2 encPos) {
return encPos.x>>28;
}
ivec3 extractLoDPosition(uvec2 encPos) {
int y = ((int(encPos.x)<<4)>>24);
int x = (int(encPos.y)<<4)>>8;
int z = int((encPos.x&((1u<<20)-1))<<4);
z |= int(encPos.y>>28);
z <<= 8;
z >>= 8;
return ivec3(x,y,z);
}
vec4 getFaceSize(uint faceData) {
float EPSILON = 0.00005f;
vec4 faceOffsetsSizes = extractFaceSizes(faceData);
//Expand the quads by a very small amount (because of the subtraction after this also becomes an implicit add)
faceOffsetsSizes.xz -= vec2(EPSILON);
//Make the end relative to the start
faceOffsetsSizes.yw -= faceOffsetsSizes.xz;
return faceOffsetsSizes;
}
vec2 taaOffset = vec2(0);//TODO: compute this
struct QuadData {
uvec4 attributeData;
float lodScale;
uint axis;
//Used for computing the 4 corners of the quad
vec3 basePoint;
vec2 quadSizeAddin;
vec2 uvCorner;
};
uint makeQuadFlags(uint faceData, uint modelId, ivec2 quadSize, const in BlockModel model, uint face) {
//bit: 0-use cuttout, 1-dont use mipmaps, 2|3-tint state, 4|6-face, 8|11-width, 12|15-height, 16|31-model id
uint flags = 0;
flags |= modelId<<16;//Model id
flags |= (uint(quadSize.x-1)<<8)|(uint(quadSize.y-1)<<12);//quad size
{//Cuttout
flags |= faceHasAlphaCuttout(faceData);
flags |= uint(any(greaterThan(quadSize, ivec2(1)))) & faceHasAlphaCuttoutOverride(faceData);
}
flags |= uint(!modelHasMipmaps(model))<<1;//Not mipmaps
flags |= faceTintState(faceData)<<2;
flags |= face<<4;//Face
return flags;
}
uint packVec4(vec4 vec) {
uvec4 vec_=uvec4(vec*255)<<uvec4(24,16,8,0);
return vec_.x|vec_.y|vec_.z|vec_.w;
}
uvec3 makeRemainingAttributes(const in BlockModel model, const in Quad quad, uint lodLevel, uint face) {
uvec3 attributes = uvec3(0);
uint lighting = extractLightId(quad);
//Apply model colour tinting
uint tintColour = model.colourTint;
if (modelHasBiomeLUT(model)) {
tintColour = colourData[tintColour + extractBiomeId(quad)];
}
#ifdef PATCHED_SHADER
attributes.x = lighting;
attributes.y = tintColour;
#else
bool isTranslucent = modelIsTranslucent(model);
bool hasAO = modelHasMipmaps(model);//TODO: replace with per face AO flag
bool isShaded = hasAO;//TODO: make this a per face flag
vec4 tinting = getLighting(lighting);
uint conditionalTinting = 0;
if (tintColour != uint(-1)) {
conditionalTinting = tintColour;
}
uint addin = 0;
if (!isTranslucent) {
tinting.w = 0.0;
//Encode the face, the lod level and
uint encodedData = 0;
encodedData |= face;
encodedData |= (lodLevel<<3);
encodedData |= uint(hasAO)<<6;
addin = encodedData;
}
//Apply face tint
#ifdef DARKENED_TINTING
if (isShaded) {
//TODO: make branchless, infact apply ahead of time to the texture itself in ModelManager since that is
// per face
if ((face>>1) == 1) {//NORTH, SOUTH
tinting.xyz *= 0.8f;
} else if ((face>>1) == 2) {//EAST, WEST
tinting.xyz *= 0.6f;
} else {//UP DOWN
tinting.xyz *= 0.9f;
}
} else {
tinting.xyz *= 0.9f;
}
#else
if (isShaded) {
//TODO: make branchless, infact apply ahead of time to the texture itself in ModelManager since that is
// per face
if ((face>>1) == 1) {//NORTH, SOUTH
tinting.xyz *= 0.8f;
} else if ((face>>1) == 2) {//EAST, WEST
tinting.xyz *= 0.6f;
} else if (face == 0) {//DOWN
tinting.xyz *= 0.5f;
}
}
#endif
attributes.x = packVec4(tinting);
attributes.y = conditionalTinting;
attributes.z = addin|(face<<8);
#endif
return attributes;
}
void setupQuad(out QuadData quad, const in Quad rawQuad, uvec2 sPos, bool generateAttributes) {
uint lodLevel = extractDetail(sPos);
float lodScale = 1<<lodLevel;
ivec3 baseSection = (extractLoDPosition(sPos)<<lodLevel) - baseSectionPos;
uint face = extractFace(rawQuad);
uint modelId = extractStateId(rawQuad);
BlockModel model = modelData[modelId];
uint faceData = model.faceData[face];
ivec2 quadSize = extractSize(rawQuad);
if (generateAttributes) {
quad.attributeData.x = makeQuadFlags(faceData, modelId, quadSize, model, face);
quad.attributeData.yzw = makeRemainingAttributes(model, rawQuad, lodLevel, face);
}
vec4 faceSize = getFaceSize(faceData);
vec3 quadStart = extractPos(rawQuad);
float depthOffset = extractFaceIndentation(faceData);
quadStart += swizzelDataAxis(face>>1, vec3(faceSize.xz, mix(depthOffset, 1-depthOffset, float(face&1u))));
quad.lodScale = lodScale;
quad.axis = face>>1;
quad.basePoint = (quadStart*lodScale)+vec3(baseSection<<5);
quad.quadSizeAddin = (faceSize.yw + quadSize - 1);
quad.uvCorner = faceSize.xz;
}
vec4 getQuadCornerPos(in QuadData quad, uint cornerId) {
vec2 cornerMask = vec2((cornerId>>1)&1u, cornerId&1u)*quad.lodScale;
vec3 point = quad.basePoint + swizzelDataAxis(quad.axis,vec3(quad.quadSizeAddin*cornerMask,0));
vec4 pos = MVP * vec4(point, 1.0f);
pos.xy += taaOffset*pos.w;
return pos;
}
#ifdef USE_INTERPOLATED_UV
vec2 getCornerUV(const in QuadData quad, uint cornerId) {
return quad.uvCorner + quad.quadSizeAddin*vec2((cornerId>>1)&1u, cornerId&1u);
}
#endif