e
This commit is contained in:
@@ -5,10 +5,8 @@
|
|||||||
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
||||||
layout(binding = 2) uniform sampler2D depthTex;
|
layout(binding = 2) uniform sampler2D depthTex;
|
||||||
|
|
||||||
layout(location=1) perprimitiveNV in PerPrimData {
|
perprimitiveNV in uvec4 primData;
|
||||||
uvec4 data;
|
perprimitiveNV in vec4 uvData;
|
||||||
vec4 uvData;
|
|
||||||
} primIn;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColour;
|
layout(location = 0) out vec4 outColour;
|
||||||
|
|
||||||
@@ -17,33 +15,33 @@ vec4 uint2vec4RGBA(uint colour) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool useMipmaps() {
|
bool useMipmaps() {
|
||||||
return (primIn.data.x&2u)==0u;
|
return (primData.x&2u)==0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useTinting() {
|
bool useTinting() {
|
||||||
return (primIn.data.x&4u)!=0u;
|
return (primData.x&4u)!=0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useCutout() {
|
bool useCutout() {
|
||||||
return (primIn.data.x&1u)==1u;
|
return (primData.x&1u)==1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 computeColour(vec4 colour) {
|
vec4 computeColour(vec4 colour) {
|
||||||
//Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha
|
//Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha
|
||||||
if (useTinting() && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) {
|
if (useTinting() && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) {
|
||||||
colour *= uint2vec4RGBA(primIn.data.z).yzwx;
|
colour *= uint2vec4RGBA(primData.z).yzwx;
|
||||||
}
|
}
|
||||||
return (colour * uint2vec4RGBA(primIn.data.y)) + vec4(0,0,0,float(primIn.data.w&0xFFu)/255);
|
return (colour * uint2vec4RGBA(primData.y)) + vec4(0,0,0,float(primData.w&0xFFu)/255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint getFace() {
|
uint getFace() {
|
||||||
return (primIn.data.w>>8)&7u;
|
return (primData.w>>8)&7u;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 getBaseUV() {
|
vec2 getBaseUV() {
|
||||||
uint face = getFace();
|
uint face = getFace();
|
||||||
uint modelId = primIn.data.x>>16;
|
uint modelId = primData.x>>16;
|
||||||
vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0));
|
vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0));
|
||||||
return modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0)));
|
return modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0)));
|
||||||
}
|
}
|
||||||
@@ -62,7 +60,7 @@ void main() {
|
|||||||
//vec2(0,gl_BaryCoordNV.x)+vec2(gl_BaryCoordNV.y,gl_BaryCoordNV.y)+vec2(gl_BaryCoordNV.z,0);
|
//vec2(0,gl_BaryCoordNV.x)+vec2(gl_BaryCoordNV.y,gl_BaryCoordNV.y)+vec2(gl_BaryCoordNV.z,0);
|
||||||
|
|
||||||
|
|
||||||
vec2 uv = fma(mix(gl_BaryCoordNV.zx+gl_BaryCoordNV.y, gl_BaryCoordNV.yx, bvec2(tri0)), primIn.uvData.zw, primIn.uvData.xy);
|
vec2 uv = fma(mix(gl_BaryCoordNV.zx+gl_BaryCoordNV.y, gl_BaryCoordNV.yx, bvec2(tri0)), uvData.zw, uvData.xy);
|
||||||
//Need to interpolate
|
//Need to interpolate
|
||||||
|
|
||||||
//Tile is the tile we are in
|
//Tile is the tile we are in
|
||||||
@@ -79,7 +77,7 @@ void main() {
|
|||||||
colour = textureLod(blockModelAtlas, texPos, 0);
|
colour = textureLod(blockModelAtlas, texPos, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any(notEqual(clamp(tile, vec2(0), vec2((primIn.data.x>>8)&0xFu, (primIn.data.x>>12)&0xFu)), tile))) {
|
if (any(notEqual(clamp(tile, vec2(0), vec2((primData.x>>8)&0xFu, (primData.x>>12)&0xFu)), tile))) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,8 @@ layout(std430) taskNV in Task {
|
|||||||
uint quadCount;
|
uint quadCount;
|
||||||
} task;
|
} task;
|
||||||
|
|
||||||
layout(location=1) perprimitiveNV out PerPrimData {
|
perprimitiveNV out uvec4 primData[MESH_SIZE*2];
|
||||||
uvec4 data;
|
perprimitiveNV out vec4 uvData[MESH_SIZE*2];
|
||||||
vec4 uvData;
|
|
||||||
} primOut[];
|
|
||||||
|
|
||||||
|
|
||||||
uint getQuadId() {
|
uint getQuadId() {
|
||||||
uint mid = gl_GlobalInvocationID.x;
|
uint mid = gl_GlobalInvocationID.x;
|
||||||
@@ -260,31 +257,44 @@ void main() {
|
|||||||
Quad quad = quadData[qid];
|
Quad quad = quadData[qid];
|
||||||
setup(quad);
|
setup(quad);
|
||||||
|
|
||||||
subgroupBarrier();
|
|
||||||
|
|
||||||
|
|
||||||
bool render = dot(faceNormal(face), cornerPos-cameraSubPos) <= 0;
|
bool render = dot(faceNormal(face), cornerPos-cameraSubPos) <= 0;
|
||||||
|
subgroupBarrier();
|
||||||
|
uint qId = subgroupExclusiveAdd(render?1:0);
|
||||||
if (render) {
|
if (render) {
|
||||||
vec4 p1 = emitVertexPos(1);
|
|
||||||
vec4 p2 = emitVertexPos(2);
|
|
||||||
vec4 p0 = emitVertexPos(0);
|
|
||||||
vec4 p3 = emitVertexPos(3);
|
|
||||||
|
|
||||||
uvec4 data = createQuadData(quad);
|
uvec4 data = createQuadData(quad);
|
||||||
|
|
||||||
subgroupBarrier();
|
subgroupBarrier();
|
||||||
uint triId_ = subgroupExclusiveAdd(2);
|
primData[qId*2] = data;
|
||||||
uint triId = triId_;
|
uvData[qId*2] = vec4(faceSize.xz, axisFaceSize);
|
||||||
uint vertId_ = subgroupExclusiveAdd(4);
|
primData[qId*2+1] = data;
|
||||||
uint vertId = vertId_;
|
uvData[qId*2+1] = vec4(faceSize.xz, axisFaceSize);
|
||||||
uint idxId = triId*3;
|
|
||||||
|
|
||||||
|
#define VID(i) (gl_LocalInvocationIndex*4+i)
|
||||||
|
|
||||||
|
gl_MeshVerticesNV[VID(0)].gl_Position = emitVertexPos(1);
|
||||||
|
gl_MeshVerticesNV[VID(1)].gl_Position = emitVertexPos(2);
|
||||||
|
|
||||||
|
gl_MeshVerticesNV[VID(2)].gl_Position = emitVertexPos(0);
|
||||||
|
gl_MeshVerticesNV[VID(3)].gl_Position = emitVertexPos(3);
|
||||||
|
|
||||||
|
gl_PrimitiveIndicesNV[qId*6+0] = VID(0);
|
||||||
|
gl_PrimitiveIndicesNV[qId*6+1] = VID(1);
|
||||||
|
gl_PrimitiveIndicesNV[qId*6+2] = VID(2);
|
||||||
|
|
||||||
|
gl_PrimitiveIndicesNV[qId*6+3] = VID(0);
|
||||||
|
gl_PrimitiveIndicesNV[qId*6+4] = VID(3);
|
||||||
|
gl_PrimitiveIndicesNV[qId*6+5] = VID(1);
|
||||||
|
|
||||||
|
gl_MeshPrimitivesNV[qId*2].gl_PrimitiveID = int(qid|(0u<<31));
|
||||||
|
gl_MeshPrimitivesNV[qId*2+1].gl_PrimitiveID = int(qid|(1u<<31));
|
||||||
|
|
||||||
|
/*
|
||||||
|
//vec4 p1 = ;
|
||||||
|
//vec4 p2 = ;
|
||||||
|
//vec4 p0 = emitVertexPos(0);
|
||||||
|
//vec4 p3 = emitVertexPos(3);
|
||||||
|
|
||||||
//Emit common
|
//Emit common
|
||||||
gl_MeshVerticesNV[vertId++].gl_Position = p1;
|
|
||||||
gl_MeshVerticesNV[vertId++].gl_Position = p2;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
gl_PrimitiveIndicesNV[idxId++] = vertId_+0;
|
gl_PrimitiveIndicesNV[idxId++] = vertId_+0;
|
||||||
@@ -309,11 +319,13 @@ void main() {
|
|||||||
primOut[triId].uvData = vec4(faceSize.xz, axisFaceSize);
|
primOut[triId].uvData = vec4(faceSize.xz, axisFaceSize);
|
||||||
gl_MeshPrimitivesNV[triId++].gl_PrimitiveID = int(qid|(1u<<31));
|
gl_MeshPrimitivesNV[triId++].gl_PrimitiveID = int(qid|(1u<<31));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
subgroupBarrier();
|
subgroupBarrier();
|
||||||
uint count = subgroupMax(triId_+2);
|
uint count = subgroupMax(qId);
|
||||||
if (subgroupElect()) {
|
if (count != 0 && subgroupElect()) {
|
||||||
|
count = count *2+2;
|
||||||
gl_PrimitiveCountNV = count;
|
gl_PrimitiveCountNV = count;
|
||||||
#ifdef HAS_STATISTICS
|
#ifdef HAS_STATISTICS
|
||||||
atomicAdd(quadCounts[task.lodLvl], count);
|
atomicAdd(quadCounts[task.lodLvl], count);
|
||||||
|
|||||||
154
src/main/resources/assets/voxy/shaders/lod/mesh/task2.glsl
Normal file
154
src/main/resources/assets/voxy/shaders/lod/mesh/task2.glsl
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#version 460 core
|
||||||
|
|
||||||
|
#extension GL_NV_mesh_shader : require
|
||||||
|
|
||||||
|
layout(local_size_x=4) in;
|
||||||
|
|
||||||
|
#import <voxy:lod/section.glsl>
|
||||||
|
|
||||||
|
bvec3 and(bvec3 a, bvec3 b) {
|
||||||
|
return bvec3(a.x&&b.x, a.y&&b.y, a.z&&b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform SceneUniform {
|
||||||
|
mat4 MVP;
|
||||||
|
ivec3 baseSectionPos;
|
||||||
|
uint frameId;
|
||||||
|
vec3 cameraSubPos;
|
||||||
|
uint pad_;
|
||||||
|
vec2 screenSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 1, std430) restrict readonly buffer IndirectSectionLookupBuffer {
|
||||||
|
uint sectionCount;
|
||||||
|
uint indirectLookup[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 2, std430) restrict readonly buffer SectionBuffer {
|
||||||
|
SectionMeta sectionData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 3, std430) restrict readonly buffer VisibilityBuffer {
|
||||||
|
uint visibilityData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAS_STATISTICS
|
||||||
|
layout(binding = STATISTICS_BUFFER_BINDING, std430) restrict buffer statisticsBuffer {
|
||||||
|
uint visibleSectionCounts[5];
|
||||||
|
uint quadCounts[5];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
taskNV out Task {
|
||||||
|
uvec4 control;//the control vec it defines what subvector to use, it is effectivly the terminating ranges of each bin
|
||||||
|
uvec4 bins[4];//the bins for each section the last component of each bin is the quad offset
|
||||||
|
|
||||||
|
uint launchSize;
|
||||||
|
} task;
|
||||||
|
|
||||||
|
#define BIN(br, cnt) if (br) { if (!pset) {bin[i++] = (sum<<16)|off;} sum += cnt; } pset = br; off += cnt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
void createBin(out uvec4 bin, out uint sum, out uint offset, uint dsc, bvec3 a, bvec3 b, uvec3 cA, uvec3 cB) {
|
||||||
|
bin = uvec4(-1);
|
||||||
|
|
||||||
|
bool pset = false;
|
||||||
|
uint i = 0;
|
||||||
|
sum = 0;
|
||||||
|
offset = counts.x&0xFFFFu;//translucent quads
|
||||||
|
|
||||||
|
uint dsc = counts.x>>16;//double sided quads
|
||||||
|
|
||||||
|
uint off = counts.x&0xFFFFu;//translucent quads
|
||||||
|
uint i = 0;
|
||||||
|
|
||||||
|
BIN(dsc!=0, dsc);//Double sided quads
|
||||||
|
|
||||||
|
|
||||||
|
BIN(a.x, cA.x);//Down
|
||||||
|
BIN(b.x, cB.x);//Up
|
||||||
|
BIN(a.y, cA.y);//North
|
||||||
|
BIN(b.y, cB.y);//South
|
||||||
|
BIN(a.z, cA.z);//West
|
||||||
|
BIN(b.z, cB.z);//East
|
||||||
|
}*/
|
||||||
|
|
||||||
|
uint fillBins(uvec4 counts, ivec3 relative) {//Returns quad count
|
||||||
|
uvec3 cA = counts.yzw&0xFFFFu;
|
||||||
|
uvec3 cB = counts.yzw>>16;
|
||||||
|
|
||||||
|
bvec3 a = and(notEqual(cA, uvec3(0)), lessThanEqual(ivec3(0), relative.yzx));
|
||||||
|
bvec3 b = and(notEqual(cB, uvec3(0)), lessThanEqual(relative.yzx, ivec3(0)));
|
||||||
|
|
||||||
|
//compute the merged bin values
|
||||||
|
uvec4 bin = uvec4(-1);
|
||||||
|
|
||||||
|
bool pset = false;
|
||||||
|
uint i = 0;
|
||||||
|
uint sum = 0;
|
||||||
|
uint offset = counts.x&0xFFFFu;//translucent quads
|
||||||
|
|
||||||
|
uint dsc = counts.x>>16;//double sided quads
|
||||||
|
|
||||||
|
uint off = counts.x&0xFFFFu;//translucent quads
|
||||||
|
uint i = 0;
|
||||||
|
|
||||||
|
BIN(dsc!=0, dsc);//Double sided quads
|
||||||
|
|
||||||
|
|
||||||
|
BIN(a.x, cA.x);//Down
|
||||||
|
BIN(b.x, cB.x);//Up
|
||||||
|
BIN(a.y, cA.y);//North
|
||||||
|
BIN(b.y, cB.y);//South
|
||||||
|
BIN(a.z, cA.z);//West
|
||||||
|
BIN(b.z, cB.z);//East
|
||||||
|
|
||||||
|
//bin contains filled bin data, non filled slots contain -1
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if (sectionCount<=gl_GlobalInvocationID.x) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (subgroupElect()) {
|
||||||
|
task.quadCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint secId = indirectLookup[gl_GlobalInvocationID.x];
|
||||||
|
uint vis = visibilityData[secId];
|
||||||
|
|
||||||
|
bool shouldRender = (vis&0x7fffffffu) == frameId-1;//-1 since we are technically in the next frame for the primary rasterization
|
||||||
|
bool renderTemporally = (vis&0x80000000u)==0;// If we are the temporal specialization, only render if marked as render temporally
|
||||||
|
|
||||||
|
if (shouldRender) {
|
||||||
|
SectionMeta section = sectionData[secId];
|
||||||
|
|
||||||
|
uint detail = extractDetail(section);
|
||||||
|
ivec3 ipos = extractPosition(section);
|
||||||
|
|
||||||
|
ivec3 relative = ipos-(baseSectionPos>>detail);
|
||||||
|
|
||||||
|
#ifdef HAS_STATISTICS
|
||||||
|
atomicAdd(visibleSectionCounts[detail], 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//TODO: here enqueue the id here for both translucent and temporal (if relevant) (* note technically dont need for temporal as can just check :tm: if we are in temporal render mode)
|
||||||
|
|
||||||
|
//TODO: in the temporal phase, extract the sections that are ment to be rendered and are also translucent
|
||||||
|
// enqueue them into a seperate buffer and increment the bin counters based on distance
|
||||||
|
// this should allow a massive simplificattion of the raster pipeline by eliminating all command gen shaders + prep shaders
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
task.baseQuad = extractQuadStart(section);
|
||||||
|
task.quadCount = fillBins(section.b, relative);
|
||||||
|
|
||||||
|
task.cameraOffset = vec3(((ipos<<detail) - baseSectionPos)<<5);
|
||||||
|
task.lodLvl = detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_TaskCountNV = (task.quadCount+(MESH_SIZE-1))/MESH_SIZE;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user