Remove nvmesh and gl46 meshlets for the time being
This commit is contained in:
@@ -1,99 +0,0 @@
|
|||||||
#line 1
|
|
||||||
struct Frustum {
|
|
||||||
vec4 planes[6];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 0, std140) uniform SceneUniform {
|
|
||||||
mat4 MVP;
|
|
||||||
ivec3 baseSectionPos;
|
|
||||||
int sectionCount;
|
|
||||||
Frustum frustum;
|
|
||||||
vec3 cameraSubPos;
|
|
||||||
uint frameId;
|
|
||||||
uvec2 screensize;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlockModel {
|
|
||||||
uint faceData[6];
|
|
||||||
uint flagsA;
|
|
||||||
uint colourTint;
|
|
||||||
uint _pad[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SectionMeta {
|
|
||||||
uint posA;
|
|
||||||
uint posB;
|
|
||||||
uint AABB;
|
|
||||||
uint ptr;
|
|
||||||
uint cntA;
|
|
||||||
uint cntB;
|
|
||||||
uint cntC;
|
|
||||||
uint cntD;
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO: see if making the stride 2*4*4 bytes or something cause you get that 16 byte write
|
|
||||||
struct DrawCommand {
|
|
||||||
uint count;
|
|
||||||
uint instanceCount;
|
|
||||||
uint firstIndex;
|
|
||||||
int baseVertex;
|
|
||||||
uint baseInstance;
|
|
||||||
};
|
|
||||||
struct DispatchIndirect {
|
|
||||||
uint x;
|
|
||||||
uint y;
|
|
||||||
uint z;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef BIND_SAMPLER_AS_HIZ
|
|
||||||
layout(binding = 0) uniform sampler2DShadow hizSampler;
|
|
||||||
#else
|
|
||||||
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Quad
|
|
||||||
#define Quad ivec2
|
|
||||||
#endif
|
|
||||||
layout(binding = 1, std430) readonly restrict buffer GeometryBuffer {
|
|
||||||
Quad geometryPool[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 2, std430) restrict buffer DrawBuffer {
|
|
||||||
DispatchIndirect dispatchCmd;
|
|
||||||
uint fullMeshletCount;
|
|
||||||
DrawCommand drawCmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 3, std430) restrict buffer MeshletListData {
|
|
||||||
uint meshlets[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 4, std430) readonly restrict buffer SectionBuffer {
|
|
||||||
SectionMeta sectionData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef VISIBILITY_ACCESS
|
|
||||||
#define VISIBILITY_ACCESS readonly
|
|
||||||
#endif
|
|
||||||
layout(binding = 5, std430) VISIBILITY_ACCESS restrict buffer VisibilityBuffer {
|
|
||||||
uint visibilityData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 6, std430) readonly restrict buffer ModelBuffer {
|
|
||||||
BlockModel modelData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 7, std430) readonly restrict buffer ModelColourBuffer {
|
|
||||||
uint colourData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 8, std430) readonly restrict buffer LightingBuffer {
|
|
||||||
uint lightData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
vec4 getLighting(uint index) {
|
|
||||||
uvec4 arr = uvec4(lightData[index]);
|
|
||||||
arr = arr>>uvec4(16,8,0,24);
|
|
||||||
arr = arr & uvec4(0xFF);
|
|
||||||
return vec4(arr)*vec4(1.0f/255.0f);
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
#version 450
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
|
||||||
|
|
||||||
#define MESHLET_ACCESS writeonly
|
|
||||||
#import <voxy:lod/quad_format.glsl>
|
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/section.glsl>
|
|
||||||
#import <voxy:lod/gl46mesh/meshlet.glsl>
|
|
||||||
|
|
||||||
layout(local_size_x = 64) in;
|
|
||||||
|
|
||||||
void emitMeshlets(inout uint mli, inout uint meshletPtr, uint mskedCnt, uint cnt) {
|
|
||||||
for (;mskedCnt != 0; mskedCnt--,mli++) {
|
|
||||||
meshlets[mli] = meshletPtr + (mskedCnt-1);
|
|
||||||
}
|
|
||||||
meshletPtr += cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
//Clear here as it stops the need to dispatch a glClearData instruction
|
|
||||||
if (gl_GlobalInvocationID.x == 0) {
|
|
||||||
drawCmd.instanceCount = 0;
|
|
||||||
dispatchCmd.y = 1;
|
|
||||||
dispatchCmd.z = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gl_GlobalInvocationID.x >= sectionCount) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check the occlusion data from last frame
|
|
||||||
bool shouldRender = visibilityData[gl_GlobalInvocationID.x] == frameId;
|
|
||||||
if (shouldRender) {
|
|
||||||
SectionMeta meta = sectionData[gl_GlobalInvocationID.x];
|
|
||||||
uint detail = extractDetail(meta);
|
|
||||||
ivec3 ipos = extractPosition(meta);
|
|
||||||
|
|
||||||
ivec3 relative = ipos-(baseSectionPos>>detail);
|
|
||||||
|
|
||||||
uint a = ((meta.cntA>>16)&0xFFFF);
|
|
||||||
uint u = (meta.cntB &0xFFFF) * uint(relative.y>-1);
|
|
||||||
uint d = ((meta.cntB>>16)&0xFFFF) * uint(relative.y<1 );
|
|
||||||
uint s = (meta.cntC &0xFFFF) * uint(relative.z>-1);
|
|
||||||
uint n = ((meta.cntC>>16)&0xFFFF) * uint(relative.z<1 );
|
|
||||||
uint w = (meta.cntD &0xFFFF) * uint(relative.x>-1);
|
|
||||||
uint e = ((meta.cntD>>16)&0xFFFF) * uint(relative.x<1 );
|
|
||||||
uint total = a + u + d + s + n + w + e;
|
|
||||||
|
|
||||||
uint mli = atomicAdd(fullMeshletCount, total);//meshletListIndex
|
|
||||||
//Need to increment the glDispatchComputeIndirect with respect to the workgroup
|
|
||||||
uint addWorkAmount = ((mli+total)>>7)-(mli>>7);//the >>7 is cause the workgroup size is 128
|
|
||||||
addWorkAmount += uint(mli==0); //If we where the first to add to the meshlet counter then we need to add an extra dispatch
|
|
||||||
// to account for trailing data
|
|
||||||
atomicAdd(dispatchCmd.x, addWorkAmount);
|
|
||||||
|
|
||||||
uint meshletPtr = extractMeshletStart(meta) + (meta.cntA&0xFFFF);
|
|
||||||
|
|
||||||
emitMeshlets(mli, meshletPtr, a, a);
|
|
||||||
emitMeshlets(mli, meshletPtr, u, (meta.cntB &0xFFFF));
|
|
||||||
emitMeshlets(mli, meshletPtr, d, ((meta.cntB>>16)&0xFFFF));
|
|
||||||
emitMeshlets(mli, meshletPtr, s, (meta.cntC &0xFFFF));
|
|
||||||
emitMeshlets(mli, meshletPtr, n, ((meta.cntC>>16)&0xFFFF));
|
|
||||||
emitMeshlets(mli, meshletPtr, w, (meta.cntD &0xFFFF));
|
|
||||||
emitMeshlets(mli, meshletPtr, e, ((meta.cntD>>16)&0xFFFF));
|
|
||||||
//TODO: also increment a secondary atomic buffer that can be used to do a compute pass over all meshlets (need to basicly divide the meshletCounter by the computes workGroup size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
#define VISIBILITY_ACCESS writeonly
|
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
|
||||||
layout(early_fragment_tests) in;
|
|
||||||
|
|
||||||
flat in uint id;
|
|
||||||
flat in uint value;
|
|
||||||
out vec4 colour;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
visibilityData[id] = value;
|
|
||||||
colour = vec4(float(id&7u)/7, float((id>>3)&7u)/7, float((id>>6)&7u)/7, 1);
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
|
||||||
#define VISIBILITY_ACCESS writeonly
|
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/section.glsl>
|
|
||||||
|
|
||||||
flat out uint id;
|
|
||||||
flat out uint value;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint sid = gl_InstanceID;
|
|
||||||
|
|
||||||
SectionMeta section = sectionData[sid];
|
|
||||||
|
|
||||||
uint detail = extractDetail(section);
|
|
||||||
ivec3 ipos = extractPosition(section);
|
|
||||||
ivec3 aabbOffset = extractAABBOffset(section);
|
|
||||||
ivec3 size = extractAABBSize(section);
|
|
||||||
|
|
||||||
//Transform ipos with respect to the vertex corner
|
|
||||||
ivec3 pos = (((ipos<<detail)-baseSectionPos)<<5);
|
|
||||||
pos += (aabbOffset-1)*(1<<detail);
|
|
||||||
pos += (ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1)*(size+2))*(1<<detail);
|
|
||||||
|
|
||||||
gl_Position = MVP * vec4(vec3(pos),1);
|
|
||||||
|
|
||||||
//Write to this id
|
|
||||||
id = sid;
|
|
||||||
value = frameId;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#define extractMeshletStart extractQuadStart
|
|
||||||
#define PosHeader Quad
|
|
||||||
#define AABBHeader Quad
|
|
||||||
|
|
||||||
//There are 16 bytes of metadata at the start of the meshlet
|
|
||||||
#define MESHLET_SIZE (QUADS_PER_MESHLET+2)
|
|
||||||
|
|
||||||
#ifdef GL_ARB_gpu_shader_int64
|
|
||||||
ivec3 extractPosition(PosHeader pos64) {
|
|
||||||
//((long)lvl<<60)|((long)(y&0xFF)<<52)|((long)(z&((1<<24)-1))<<28)|((long)(x&((1<<24)-1))<<4);
|
|
||||||
//return ivec3((pos64<<4)&uint64_t(0xFFFFFFFF),(pos64>>28)&uint64_t(0xFFFFFFFF),(pos64>>24)&uint64_t(0xFFFFFFFF))>>ivec3(8,24,8);
|
|
||||||
return (ivec3(int(pos64>>4)&((1<<24)-1), int(pos64>>52)&0xFF, int(pos64>>28)&((1<<24)-1))<<ivec3(8,24,8))>>ivec3(8,24,8);
|
|
||||||
}
|
|
||||||
uint extractDetail(PosHeader pos64) {
|
|
||||||
return uint(pos64>>60);
|
|
||||||
}
|
|
||||||
uvec3 extractMin(AABBHeader aabb) {
|
|
||||||
return uvec3(uint(uint(aabb)&0xFF),uint((uint(aabb)>>8)&0xFF),uint((uint(aabb)>>16)&0xFF));
|
|
||||||
}
|
|
||||||
uvec3 extractMax(AABBHeader aabb) {
|
|
||||||
return uvec3(uint((aabb>>24)&0xFF),uint((aabb>>32)&0xFF),uint((aabb>>40)&0xFF));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ivec3 extractPosition(PosHeader pos) {
|
|
||||||
int y = ((int(pos.x)<<4)>>24);
|
|
||||||
int x = (int(pos.y)<<4)>>8;
|
|
||||||
int z = int((pos.x&((1<<20)-1))<<4);
|
|
||||||
z |= int(pos.y>>28)&0xF;
|
|
||||||
z <<= 8;
|
|
||||||
z >>= 8;
|
|
||||||
return ivec3(x,y,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint extractDetail(PosHeader pos) {
|
|
||||||
return uint(pos.x)>>28;
|
|
||||||
}
|
|
||||||
|
|
||||||
uvec3 extractMin(AABBHeader aabb) {
|
|
||||||
return uvec3(aabb.x&0xFF,(aabb.x>>8)&0xFF,(aabb.x>>16)&0xFF);
|
|
||||||
}
|
|
||||||
uvec3 extractMax(AABBHeader aabb) {
|
|
||||||
return uvec3((aabb.x>>24)&0xFF,aabb.y&0xFF,(aabb.y>>8)&0xFF);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#version 450
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
|
||||||
|
|
||||||
#define MESHLET_ACCESS
|
|
||||||
#define BIND_SAMPLER_AS_HIZ
|
|
||||||
#import <voxy:lod/quad_format.glsl>
|
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/section.glsl>
|
|
||||||
#import <voxy:lod/gl46mesh/meshlet.glsl>
|
|
||||||
layout(local_size_x=128) in;
|
|
||||||
|
|
||||||
vec3 proj(vec3 pos) {
|
|
||||||
vec4 t = MVP * vec4(vec3(pos),1);
|
|
||||||
return t.xyz/t.w;
|
|
||||||
}
|
|
||||||
bool testHiZ(PosHeader secPos, AABBHeader aabb) {
|
|
||||||
ivec3 section = extractPosition(secPos);
|
|
||||||
uint detail = extractDetail(secPos);
|
|
||||||
vec3 pos = vec3(ivec3(((section<<detail)-baseSectionPos)<<5));
|
|
||||||
vec3 cmin = ivec3(extractMin(aabb)*(1<<detail));
|
|
||||||
vec3 cmax = ivec3((extractMax(aabb)+1)*(1<<detail));
|
|
||||||
|
|
||||||
|
|
||||||
//TODO:FIXME: either pos,cmin,cmax isnt correct, aswell as the miplevel isnt correct as its sampling at the wrong detail level
|
|
||||||
|
|
||||||
vec3 minBB = proj(pos + cmin);//
|
|
||||||
vec3 maxBB = minBB;
|
|
||||||
|
|
||||||
for (int i = 1; i < 8; i++) {
|
|
||||||
vec3 point = proj(pos + mix(cmin, cmax, bvec3((i&1)!=0,(i&2)!=0,(i&4)!=0)));
|
|
||||||
minBB = min(minBB, point);
|
|
||||||
maxBB = max(maxBB, point);
|
|
||||||
}
|
|
||||||
|
|
||||||
minBB = clamp(minBB*0.5+0.5, vec3(0), vec3(1));
|
|
||||||
maxBB = clamp(maxBB*0.5+0.5, vec3(0), vec3(1));
|
|
||||||
|
|
||||||
vec2 size = (maxBB.xy - minBB.xy) * vec2(ivec2(screensize));
|
|
||||||
float miplevel = ceil(log2(max(max(size.x, size.y),1)));
|
|
||||||
/*
|
|
||||||
float a = textureLod(hizSampler,minBB.xy,miplevel).r;
|
|
||||||
float b = textureLod(hizSampler,vec2(minBB.x,maxBB.y),miplevel).r;
|
|
||||||
float c = textureLod(hizSampler,maxBB.xy,miplevel).r;
|
|
||||||
float d = textureLod(hizSampler,vec2(maxBB.x,minBB.y),miplevel).r;
|
|
||||||
float depth = max(max(a,b),max(c,d));
|
|
||||||
return minBB.z <= depth;
|
|
||||||
*/
|
|
||||||
|
|
||||||
vec2 midpoint = (maxBB.xy + minBB.xy)*0.5;
|
|
||||||
return textureLod(hizSampler, vec3(midpoint, minBB.z - 0.000000001), miplevel) > 0.0001;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
if (gl_GlobalInvocationID.x >= fullMeshletCount) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (gl_GlobalInvocationID.x == 0) {
|
|
||||||
//Setup the state of the drawElementsIndirect command, instanceCount is cleared externally
|
|
||||||
drawCmd.count = QUADS_PER_MESHLET*6;
|
|
||||||
drawCmd.firstIndex = 0;
|
|
||||||
drawCmd.baseVertex = 0;
|
|
||||||
drawCmd.baseInstance = fullMeshletCount;//Start at the begining of the newly emitted meshlet array
|
|
||||||
}
|
|
||||||
uint meshletId = meshlets[gl_GlobalInvocationID.x];
|
|
||||||
PosHeader pos = geometryPool[meshletId*MESHLET_SIZE];
|
|
||||||
AABBHeader aabb = geometryPool[meshletId*MESHLET_SIZE+1];
|
|
||||||
|
|
||||||
if (testHiZ(pos, aabb)) {//If didnt cull, insert it back into the stream
|
|
||||||
meshlets[atomicAdd(drawCmd.instanceCount, 1)+fullMeshletCount] = meshletId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
|
||||||
|
|
||||||
//TODO: need to fix when merged quads have discardAlpha set to false but they span multiple tiles
|
|
||||||
// however they are not a full block
|
|
||||||
|
|
||||||
//#define DEBUG_MESHLETS_ONLY
|
|
||||||
|
|
||||||
#ifndef DEBUG_MESHLETS_ONLY
|
|
||||||
layout(location = 0) in vec2 uv;
|
|
||||||
layout(location = 1) in flat vec2 baseUV;
|
|
||||||
layout(location = 2) in flat vec4 tinting;
|
|
||||||
layout(location = 3) in flat vec4 addin;
|
|
||||||
layout(location = 4) in flat uint flags;
|
|
||||||
layout(location = 5) in flat vec4 conditionalTinting;
|
|
||||||
#else
|
|
||||||
layout(location = 6) in flat uint meshlet;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColour;
|
|
||||||
void main() {
|
|
||||||
#ifndef DEBUG_MESHLETS_ONLY
|
|
||||||
vec2 uv = mod(uv, vec2(1.0))*(1.0/(vec2(3.0,2.0)*256.0));
|
|
||||||
//vec4 colour = solidColour;
|
|
||||||
vec4 colour = texture(blockModelAtlas, uv + baseUV, ((flags>>1)&1u)*-4.0);
|
|
||||||
if ((flags&1u) == 1 && colour.a <= 0.25f) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha
|
|
||||||
if ((flags&(1u<<2)) != 0 && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) {
|
|
||||||
colour *= conditionalTinting;
|
|
||||||
}
|
|
||||||
|
|
||||||
outColour = (colour * tinting) + addin;
|
|
||||||
|
|
||||||
//outColour = vec4(uv + baseUV, 0, 1);
|
|
||||||
#else
|
|
||||||
uint hash = meshlet*1231421+123141;
|
|
||||||
hash ^= hash>>16;
|
|
||||||
hash = hash*1231421+123141;
|
|
||||||
hash ^= hash>>16;
|
|
||||||
hash = hash * 1827364925 + 123325621;
|
|
||||||
outColour = vec4(float(hash&15u)/15, float((hash>>4)&15u)/15, float((hash>>8)&15u)/15, 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
#version 450
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
|
||||||
#extension GL_ARB_shader_draw_parameters : require
|
|
||||||
|
|
||||||
//#define DEBUG_MESHLETS_ONLY
|
|
||||||
|
|
||||||
#import <voxy:lod/quad_format.glsl>
|
|
||||||
#import <voxy:lod/gl46mesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/block_model.glsl>
|
|
||||||
#import <voxy:lod/gl46mesh/meshlet.glsl>
|
|
||||||
|
|
||||||
#ifdef DEBUG_MESHLETS_ONLY
|
|
||||||
layout(location = 6) out flat uint meshlet;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PosHeader meshletPosition;
|
|
||||||
Quad quad;
|
|
||||||
bool setupMeshlet() {
|
|
||||||
gl_CullDistance[0] = 1;
|
|
||||||
//TODO: replace with vertexAttribute that has a divisor of 1
|
|
||||||
uint data = meshlets[gl_InstanceID + gl_BaseInstanceARB];
|
|
||||||
if (data == uint(-1)) {//Came across a culled meshlet
|
|
||||||
gl_CullDistance[0] = -1;
|
|
||||||
//Since the primative is culled, dont need to do any more work or set any values as the primative is discarded
|
|
||||||
// we dont need to care about undefined values
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_MESHLETS_ONLY
|
|
||||||
meshlet = data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
uint baseId = (data*MESHLET_SIZE);
|
|
||||||
uint quadIndex = baseId + (gl_VertexID>>2) + 2;
|
|
||||||
meshletPosition = geometryPool[baseId];
|
|
||||||
quad = geometryPool[quadIndex];
|
|
||||||
if (isQuadEmpty(quad)) {
|
|
||||||
gl_CullDistance[0] = -1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DEBUG_MESHLETS_ONLY
|
|
||||||
layout(location = 0) out vec2 uv;
|
|
||||||
layout(location = 1) out flat vec2 baseUV;
|
|
||||||
layout(location = 2) out flat vec4 tinting;
|
|
||||||
layout(location = 3) out flat vec4 addin;
|
|
||||||
layout(location = 4) out flat uint flags;
|
|
||||||
layout(location = 5) out flat vec4 conditionalTinting;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec4 uint2vec4RGBA(uint colour) {
|
|
||||||
return vec4((uvec4(colour)>>uvec4(24,16,8,0))&uvec4(0xFF))/255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 getFaceSize(uint faceData) {
|
|
||||||
float EPSILON = 0.001f;
|
|
||||||
vec4 faceOffsetsSizes = extractFaceSizes(faceData);
|
|
||||||
//Expand the quads by a very small amount
|
|
||||||
faceOffsetsSizes.xz -= vec2(EPSILON);
|
|
||||||
faceOffsetsSizes.yw += vec2(EPSILON);
|
|
||||||
|
|
||||||
//Make the end relative to the start
|
|
||||||
faceOffsetsSizes.yw -= faceOffsetsSizes.xz;
|
|
||||||
|
|
||||||
return faceOffsetsSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: make branchless by using ternaries i think
|
|
||||||
vec3 swizzelDataAxis(uint axis, vec3 data) {
|
|
||||||
if (axis == 0) { //Up/down
|
|
||||||
data = data.xzy;
|
|
||||||
}
|
|
||||||
//Not needed, here for readability
|
|
||||||
//if (axis == 1) {//north/south
|
|
||||||
// offset = offset.xyz;
|
|
||||||
//}
|
|
||||||
if (axis == 2) { //west/east
|
|
||||||
data = data.zxy;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
|
|
||||||
if (setupMeshlet()) {
|
|
||||||
gl_Position = vec4(1.0f/0.0f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint lodLevel = extractDetail(meshletPosition);
|
|
||||||
ivec3 sectionPos = extractPosition(meshletPosition);
|
|
||||||
|
|
||||||
//meshlet = (meshlet<<5)|(gl_VertexID>>2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cornerIdx = gl_VertexID&3;
|
|
||||||
vec3 innerPos = extractPos(quad);
|
|
||||||
uint face = extractFace(quad);
|
|
||||||
uint modelId = extractStateId(quad);
|
|
||||||
BlockModel model = modelData[modelId];
|
|
||||||
uint faceData = model.faceData[face];
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ivec2 quadSize = extractSize(quad);
|
|
||||||
|
|
||||||
#ifndef DEBUG_MESHLETS_ONLY
|
|
||||||
//Exploit provoking vertex to do less work
|
|
||||||
//if (cornerIdx==1)
|
|
||||||
{
|
|
||||||
vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0));
|
|
||||||
baseUV = modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0)));
|
|
||||||
|
|
||||||
//Generate tinting and flag data
|
|
||||||
|
|
||||||
flags = faceHasAlphaCuttout(faceData);
|
|
||||||
|
|
||||||
//We need to have a conditional override based on if the model size is < a full face + quadSize > 1
|
|
||||||
flags |= uint(any(greaterThan(quadSize, ivec2(1)))) & faceHasAlphaCuttoutOverride(faceData);
|
|
||||||
|
|
||||||
flags |= uint(!modelHasMipmaps(model))<<1;
|
|
||||||
|
|
||||||
//Compute lighting
|
|
||||||
tinting = getLighting(extractLightId(quad));
|
|
||||||
|
|
||||||
//Apply model colour tinting
|
|
||||||
uint tintColour = model.colourTint;
|
|
||||||
if (modelHasBiomeLUT(model)) {
|
|
||||||
tintColour = colourData[tintColour + extractBiomeId(quad)];
|
|
||||||
}
|
|
||||||
|
|
||||||
conditionalTinting = vec4(0);
|
|
||||||
if (tintColour != uint(-1)) {
|
|
||||||
flags |= 1u<<2;
|
|
||||||
conditionalTinting = uint2vec4RGBA(tintColour).yzwx;
|
|
||||||
}
|
|
||||||
|
|
||||||
addin = vec4(0.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.w = float(encodedData)/255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply face tint
|
|
||||||
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) {
|
|
||||||
tinting.xyz *= 0.8f;
|
|
||||||
} else if ((face>>1) == 2) {
|
|
||||||
tinting.xyz *= 0.6f;
|
|
||||||
} else if (face == 0){
|
|
||||||
tinting.xyz *= 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vec4 faceSize = getFaceSize(faceData);
|
|
||||||
|
|
||||||
vec2 cQuadSize = (faceSize.yw + quadSize - 1) * vec2((cornerIdx>>1)&1, cornerIdx&1);
|
|
||||||
|
|
||||||
//uv = faceSize.xz + cQuadSize;
|
|
||||||
|
|
||||||
vec3 cornerPos = extractPos(quad);
|
|
||||||
float depthOffset = extractFaceIndentation(faceData);
|
|
||||||
cornerPos += swizzelDataAxis(face>>1, vec3(faceSize.xz, mix(depthOffset, 1-depthOffset, float(face&1u))));
|
|
||||||
|
|
||||||
vec3 origin = vec3(((sectionPos<<lodLevel)-baseSectionPos)<<5);
|
|
||||||
gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(cQuadSize,0)))*(1<<lodLevel)+origin, 1.0);
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
struct SectionMeta {
|
|
||||||
uint posA;
|
|
||||||
uint posB;
|
|
||||||
uint AABB;
|
|
||||||
uint ptr;
|
|
||||||
uint cntA;
|
|
||||||
uint cntB;
|
|
||||||
uint cntC;
|
|
||||||
uint cntD;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlockModel {
|
|
||||||
uint faceData[6];
|
|
||||||
uint flagsA;
|
|
||||||
uint colourTint;
|
|
||||||
uint _pad[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
|
||||||
|
|
||||||
layout(binding = 0, std140) uniform SceneUniform {
|
|
||||||
mat4 MVP;
|
|
||||||
ivec3 baseSectionPos;
|
|
||||||
int sectionCount;
|
|
||||||
vec3 cameraSubPos;
|
|
||||||
uint frameId;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define Quad uint64_t
|
|
||||||
layout(binding = 1, std430) readonly restrict buffer QuadBuffer {
|
|
||||||
Quad quadData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 2, std430) readonly restrict buffer SectionBuffer {
|
|
||||||
SectionMeta sectionData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef VISIBILITY_ACCESS
|
|
||||||
#define VISIBILITY_ACCESS readonly
|
|
||||||
#endif
|
|
||||||
layout(binding = 3, std430) VISIBILITY_ACCESS restrict buffer VisibilityBuffer {
|
|
||||||
uint visibilityData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 4, std430) readonly restrict buffer ModelBuffer {
|
|
||||||
BlockModel modelData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 5, std430) readonly restrict buffer ModelColourBuffer {
|
|
||||||
uint colourData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding = 6, std430) readonly restrict buffer LightingBuffer {
|
|
||||||
uint lightData[];
|
|
||||||
};
|
|
||||||
|
|
||||||
vec4 getLighting(uint index) {
|
|
||||||
uvec4 arr = uvec4(lightData[index]);
|
|
||||||
arr = arr>>uvec4(16,8,0,24);
|
|
||||||
arr = arr & uvec4(0xFF);
|
|
||||||
return vec4(arr)*vec4(1.0f/255.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
|
||||||
#define VISIBILITY_ACCESS writeonly
|
|
||||||
#import <voxy:lod/nvmesh/bindings.glsl>
|
|
||||||
layout(early_fragment_tests) in;
|
|
||||||
|
|
||||||
flat in uint id;
|
|
||||||
flat in uint value;
|
|
||||||
//out vec4 colour;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
visibilityData[id] = value;
|
|
||||||
//colour = vec4(float(id&7u)/7, float((id>>3)&7u)/7, float((id>>6)&7u)/7, 1);
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : enable
|
|
||||||
#define VISIBILITY_ACCESS writeonly
|
|
||||||
#import <voxy:lod/nvmesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/section.glsl>
|
|
||||||
|
|
||||||
flat out uint id;
|
|
||||||
flat out uint value;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint sid = gl_InstanceID;
|
|
||||||
|
|
||||||
SectionMeta section = sectionData[sid];
|
|
||||||
|
|
||||||
uint detail = extractDetail(section);
|
|
||||||
ivec3 ipos = extractPosition(section);
|
|
||||||
ivec3 aabbOffset = extractAABBOffset(section);
|
|
||||||
ivec3 size = extractAABBSize(section);
|
|
||||||
|
|
||||||
//Transform ipos with respect to the vertex corner
|
|
||||||
ivec3 pos = (((ipos<<detail)-baseSectionPos)<<5);
|
|
||||||
pos += (aabbOffset-1)*(1<<detail);
|
|
||||||
pos += (ivec3(gl_VertexID&1, (gl_VertexID>>2)&1, (gl_VertexID>>1)&1)*(size+2))*(1<<detail);
|
|
||||||
|
|
||||||
gl_Position = MVP * vec4(vec3(pos)-cameraSubPos,1);
|
|
||||||
|
|
||||||
//Write to this id
|
|
||||||
id = sid;
|
|
||||||
value = frameId;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#version 460 core
|
|
||||||
layout(binding = 0) uniform sampler2D blockModelAtlas;
|
|
||||||
|
|
||||||
layout(location=1) in Interpolants {
|
|
||||||
vec2 uv;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(location=2) perprimitiveNV in PerPrimData {
|
|
||||||
vec2 baseUV;
|
|
||||||
vec4 tinting;
|
|
||||||
vec4 addin;
|
|
||||||
uint flags;
|
|
||||||
vec4 conditionalTinting;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColour;
|
|
||||||
void main() {
|
|
||||||
vec2 uv = mod(uv, vec2(1.0))*(1.0/(vec2(3.0,2.0)*256.0));
|
|
||||||
vec4 colour = texture(blockModelAtlas, uv + baseUV, ((flags>>1)&1u)*-4.0);
|
|
||||||
if ((flags&1u) == 1 && colour.a <= 0.25f) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Conditional tinting, TODO: FIXME: REPLACE WITH MASK OR SOMETHING, like encode data into the top bit of alpha
|
|
||||||
if ((flags&(1u<<2)) != 0 && abs(colour.r-colour.g) < 0.02f && abs(colour.g-colour.b) < 0.02f) {
|
|
||||||
colour *= conditionalTinting;
|
|
||||||
}
|
|
||||||
|
|
||||||
outColour = (colour * tinting) + addin;
|
|
||||||
}
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
#version 460
|
|
||||||
|
|
||||||
#extension GL_ARB_shading_language_include : enable
|
|
||||||
#pragma optionNV(unroll all)
|
|
||||||
#define UNROLL_LOOP
|
|
||||||
|
|
||||||
#extension GL_NV_mesh_shader : require
|
|
||||||
#extension GL_NV_gpu_shader5 : require
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : require
|
|
||||||
|
|
||||||
#import <voxy:lod/nvmesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/block_model.glsl>
|
|
||||||
#import <voxy:lod/quad_format.glsl>
|
|
||||||
#line 13
|
|
||||||
|
|
||||||
layout(local_size_x = 16) in;
|
|
||||||
layout(triangles, max_vertices=64, max_primitives=32) out;
|
|
||||||
|
|
||||||
layout(location=1) out Interpolants {
|
|
||||||
vec2 uv;
|
|
||||||
} i_out[];
|
|
||||||
|
|
||||||
layout(location=2) perprimitiveNV out PerPrimData {
|
|
||||||
vec2 baseUV;
|
|
||||||
vec4 tinting;
|
|
||||||
vec4 addin;
|
|
||||||
uint flags;
|
|
||||||
vec4 conditionalTinting;
|
|
||||||
} per_prim_out[];
|
|
||||||
|
|
||||||
void emitIndicies() {
|
|
||||||
uint primBase = gl_LocalInvocationID.x * 6;
|
|
||||||
uint vertBase = gl_LocalInvocationID.x<<2;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+0] = vertBase+0;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+1] = vertBase+1;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+2] = vertBase+2;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+3] = vertBase+2;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+4] = vertBase+3;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+5] = vertBase+0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 uint2vec4RGBA(uint colour) {
|
|
||||||
return vec4((uvec4(colour)>>uvec4(24,16,8,0))&uvec4(0xFF))/255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 getFaceSize(uint faceData) {
|
|
||||||
float EPSILON = 0.001f;
|
|
||||||
vec4 faceOffsetsSizes = extractFaceSizes(faceData);
|
|
||||||
//Expand the quads by a very small amount
|
|
||||||
faceOffsetsSizes.xz -= vec2(EPSILON);
|
|
||||||
faceOffsetsSizes.yw += vec2(EPSILON);
|
|
||||||
|
|
||||||
//Make the end relative to the start
|
|
||||||
faceOffsetsSizes.yw -= faceOffsetsSizes.xz;
|
|
||||||
|
|
||||||
return faceOffsetsSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: make branchless by using ternaries i think
|
|
||||||
vec3 swizzelDataAxis(uint axis, vec3 data) {
|
|
||||||
if (axis == 0) { //Up/down
|
|
||||||
data = data.xzy;
|
|
||||||
}
|
|
||||||
//Not needed, here for readability
|
|
||||||
//if (axis == 1) {//north/south
|
|
||||||
// offset = offset.xyz;
|
|
||||||
//}
|
|
||||||
if (axis == 2) { //west/east
|
|
||||||
data = data.zxy;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
taskNV in Task {
|
|
||||||
vec3 origin;//Offset to camera in world space (already multiplied by lod level)
|
|
||||||
uint baseOffset;//Base offset into the quad data buffer
|
|
||||||
|
|
||||||
//Binary search indexs and data
|
|
||||||
uvec4 binIa;
|
|
||||||
uvec4 binIb;
|
|
||||||
uvec4 binVa;
|
|
||||||
uvec4 binVb;
|
|
||||||
|
|
||||||
uint meta;//First 4 bits is lod level, remaining is quadCount
|
|
||||||
};
|
|
||||||
|
|
||||||
uint getQuadIndex() {
|
|
||||||
uint gii = gl_GlobalInvocationID.x;
|
|
||||||
//TODO: replace this with binary search
|
|
||||||
if (gii < binIa.x) {
|
|
||||||
return binVa.x + gii + baseOffset;
|
|
||||||
} else if (gii < binIa.y) {
|
|
||||||
return binVa.y + (gii - binIa.x) + baseOffset;
|
|
||||||
} else if (gii < binIa.z) {
|
|
||||||
return binVa.z + (gii - binIa.y) + baseOffset;
|
|
||||||
} else if (gii < binIa.w) {
|
|
||||||
return binVa.w + (gii - binIa.z) + baseOffset;
|
|
||||||
} else if (gii < binIb.x) {
|
|
||||||
return binVb.x + (gii - binIa.w) + baseOffset;
|
|
||||||
} else if (gii < binIb.y) {
|
|
||||||
return binVb.y + (gii - binIb.x) + baseOffset;
|
|
||||||
} else if (gii < binIb.z) {
|
|
||||||
return binVb.z + (gii - binIb.y) + baseOffset;
|
|
||||||
} else if (gii < binIb.w) {
|
|
||||||
return binVb.w + (gii - binIb.z) + baseOffset;
|
|
||||||
} else {
|
|
||||||
return uint(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint idx = getQuadIndex();
|
|
||||||
//If its over, dont render
|
|
||||||
if (idx == uint(-1)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emitIndicies();
|
|
||||||
|
|
||||||
uint A = gl_LocalInvocationID.x<<1;
|
|
||||||
uint B = (gl_LocalInvocationID.x<<1)|1u;
|
|
||||||
uint V = (gl_LocalInvocationID.x<<2);
|
|
||||||
|
|
||||||
uint lodLvl = meta&0xf;
|
|
||||||
float lodScale = (1<<lodLvl);
|
|
||||||
|
|
||||||
Quad quad = quadData[idx];
|
|
||||||
uint face = extractFace(quad);
|
|
||||||
uint modelId = extractStateId(quad);
|
|
||||||
BlockModel model = modelData[modelId];
|
|
||||||
uint faceData = model.faceData[face];
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
ivec2 quadSize = extractSize(quad);
|
|
||||||
|
|
||||||
|
|
||||||
//Compute the uv coordinates
|
|
||||||
vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0));
|
|
||||||
vec2 baseUV = modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0)));
|
|
||||||
//Write out baseUV
|
|
||||||
per_prim_out[A].baseUV = baseUV;
|
|
||||||
per_prim_out[B].baseUV = baseUV;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint flags = faceHasAlphaCuttout(faceData);
|
|
||||||
|
|
||||||
//We need to have a conditional override based on if the model size is < a full face + quadSize > 1
|
|
||||||
flags |= uint(any(greaterThan(quadSize, ivec2(1)))) & faceHasAlphaCuttoutOverride(faceData);
|
|
||||||
|
|
||||||
flags |= uint(!modelHasMipmaps(model))<<1;
|
|
||||||
|
|
||||||
//Compute lighting
|
|
||||||
vec4 tinting = getLighting(extractLightId(quad));
|
|
||||||
|
|
||||||
//Apply model colour tinting
|
|
||||||
uint tintColour = model.colourTint;
|
|
||||||
if (modelHasBiomeLUT(model)) {
|
|
||||||
tintColour = colourData[tintColour + extractBiomeId(quad)];
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 conditionalTinting = vec4(0);
|
|
||||||
if (tintColour != uint(-1)) {
|
|
||||||
flags |= 1u<<2;
|
|
||||||
conditionalTinting = uint2vec4RGBA(tintColour).yzwx;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 addin = vec4(0.0);
|
|
||||||
if (!isTranslucent) {
|
|
||||||
tinting.w = 0.0;
|
|
||||||
//Encode the face, the lod level and
|
|
||||||
uint encodedData = 0;
|
|
||||||
encodedData |= face;
|
|
||||||
encodedData |= (lodLvl<<3);
|
|
||||||
encodedData |= uint(hasAO)<<6;
|
|
||||||
addin.w = float(encodedData)/255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply face tint
|
|
||||||
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) {
|
|
||||||
tinting.xyz *= 0.8f;
|
|
||||||
} else if ((face>>1) == 2) {
|
|
||||||
tinting.xyz *= 0.6f;
|
|
||||||
} else if (face == 0){
|
|
||||||
tinting.xyz *= 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Write out everything
|
|
||||||
per_prim_out[A].tinting = tinting;
|
|
||||||
per_prim_out[A].addin = addin;
|
|
||||||
per_prim_out[A].flags = flags;
|
|
||||||
per_prim_out[A].conditionalTinting = conditionalTinting;
|
|
||||||
per_prim_out[B].tinting = tinting;
|
|
||||||
per_prim_out[B].addin = addin;
|
|
||||||
per_prim_out[B].flags = flags;
|
|
||||||
per_prim_out[B].conditionalTinting = conditionalTinting;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vec4 faceSize = getFaceSize(faceData);
|
|
||||||
|
|
||||||
vec2 cQuadSize = faceSize.yw + quadSize - 1;
|
|
||||||
vec2 uv0 = faceSize.xz;
|
|
||||||
i_out[V|0].uv = uv0;
|
|
||||||
i_out[V|1].uv = uv0 + vec2(0, cQuadSize.y);
|
|
||||||
i_out[V|2].uv = uv0 + cQuadSize;
|
|
||||||
i_out[V|3].uv = uv0 + vec2(cQuadSize.x, 0);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Corner position of quad relative to section corner (in 0->32 scale)
|
|
||||||
vec3 cornerPos = extractPos(quad);
|
|
||||||
float depthOffset = extractFaceIndentation(faceData);
|
|
||||||
cornerPos += swizzelDataAxis(face>>1, vec3(faceSize.xz, mix(depthOffset, 1-depthOffset, float(face&1u))));
|
|
||||||
gl_MeshVerticesNV[V|0].gl_Position = MVP*vec4(cornerPos*lodScale+origin, 1.0);
|
|
||||||
gl_MeshVerticesNV[V|1].gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(0,cQuadSize.y,0)))*lodScale+origin, 1.0);
|
|
||||||
gl_MeshVerticesNV[V|2].gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(cQuadSize, 0)))*lodScale+origin, 1.0);
|
|
||||||
gl_MeshVerticesNV[V|3].gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(cQuadSize.x,0,0)))*lodScale+origin, 1.0);
|
|
||||||
|
|
||||||
if (gl_LocalInvocationID.x == 0) {
|
|
||||||
//Remaining quads in workgroup
|
|
||||||
gl_PrimitiveCountNV = min(uint(int(meta>>4)-int(gl_WorkGroupID.x<<4))<<1, 32);//2 primatives per quad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
#version 460
|
|
||||||
|
|
||||||
#extension GL_ARB_shading_language_include : enable
|
|
||||||
#pragma optionNV(unroll all)
|
|
||||||
#define UNROLL_LOOP
|
|
||||||
|
|
||||||
#extension GL_NV_mesh_shader : require
|
|
||||||
#extension GL_NV_gpu_shader5 : require
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : require
|
|
||||||
|
|
||||||
#import <voxy:lod/nvmesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/section.glsl>
|
|
||||||
#line 12
|
|
||||||
|
|
||||||
#define MESH_WORKLOAD_PER_INVOCATION 16
|
|
||||||
|
|
||||||
layout(local_size_x=1) in;
|
|
||||||
|
|
||||||
taskNV out Task {
|
|
||||||
vec3 origin;//Offset to camera in world space (already multiplied by lod level)
|
|
||||||
uint baseOffset;//Base offset into the quad data buffer
|
|
||||||
|
|
||||||
//Binary search indexs and data
|
|
||||||
uvec4 binIa;
|
|
||||||
uvec4 binIb;
|
|
||||||
uvec4 binVa;
|
|
||||||
uvec4 binVb;
|
|
||||||
|
|
||||||
uint meta;//First 4 bits is lod level, remaining is quadCount
|
|
||||||
} task;
|
|
||||||
|
|
||||||
|
|
||||||
void putBinData(inout uint idx, inout uint lastIndex, uint offset, uint cnt) {
|
|
||||||
uint id = idx++;
|
|
||||||
if (id < 4) {
|
|
||||||
task.binIa[id] = lastIndex + cnt;
|
|
||||||
task.binVa[id] = offset;
|
|
||||||
} else {
|
|
||||||
task.binIb[id - 4] = lastIndex + cnt;
|
|
||||||
task.binVb[id - 4] = offset;
|
|
||||||
}
|
|
||||||
lastIndex += cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint sectionId = gl_WorkGroupID.x;
|
|
||||||
bool visibleLastFrame = visibilityData[sectionId] == (frameId-1);
|
|
||||||
|
|
||||||
//If it wasnt visible last frame then dont render this frame ** (do temporal coherance)
|
|
||||||
if (!visibleLastFrame) {
|
|
||||||
gl_TaskCountNV = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SectionMeta meta = sectionData[sectionId];
|
|
||||||
uint lodLvl = extractDetail(meta);
|
|
||||||
ivec3 lodPos= extractPosition(meta);
|
|
||||||
//Relative position to camera with resepct to lod level to check for visibility bits
|
|
||||||
ivec3 cpos = lodPos-(baseSectionPos>>lodLvl);
|
|
||||||
//Relative position to camera
|
|
||||||
task.origin = vec3(((lodPos<<lodLvl)-baseSectionPos)<<5)-cameraSubPos;
|
|
||||||
|
|
||||||
task.baseOffset = extractQuadStart(meta);
|
|
||||||
task.meta = lodLvl&0xFu;
|
|
||||||
|
|
||||||
|
|
||||||
uint idx = 0;
|
|
||||||
uint lastIndex = 0;
|
|
||||||
uint offset = meta.cntA&0xFFFF;//Skip translucency
|
|
||||||
|
|
||||||
task.binIa = uvec4(0);
|
|
||||||
task.binIb = uvec4(0);
|
|
||||||
|
|
||||||
uint cnt = (meta.cntA>>16)&0xFFFF;
|
|
||||||
if (cnt!=0) {
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
cnt = meta.cntB &0xFFFF;
|
|
||||||
if ((cnt!=0) && (cpos.y>-1)) {
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
cnt = (meta.cntB>>16)&0xFFFF;
|
|
||||||
if((cnt!=0) && (cpos.y<1 )){
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
cnt = meta.cntC &0xFFFF;
|
|
||||||
if((cnt!=0) && (cpos.z>-1)){
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
cnt = (meta.cntC>>16)&0xFFFF;
|
|
||||||
if((cnt!=0) && (cpos.z<1 )){
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
cnt = meta.cntD &0xFFFF;
|
|
||||||
if((cnt!=0) && (cpos.x>-1)){
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
cnt = (meta.cntD>>16)&0xFFFF;
|
|
||||||
if((cnt!=0) && (cpos.x<1 )){
|
|
||||||
putBinData(idx, lastIndex, offset, cnt);
|
|
||||||
}
|
|
||||||
offset += cnt;
|
|
||||||
|
|
||||||
|
|
||||||
task.meta |= lastIndex<<4;
|
|
||||||
gl_TaskCountNV = (lastIndex+MESH_WORKLOAD_PER_INVOCATION-1)/MESH_WORKLOAD_PER_INVOCATION;
|
|
||||||
}
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
#version 460
|
|
||||||
|
|
||||||
#extension GL_ARB_shading_language_include : enable
|
|
||||||
#pragma optionNV(unroll all)
|
|
||||||
#define UNROLL_LOOP
|
|
||||||
|
|
||||||
#extension GL_NV_mesh_shader : require
|
|
||||||
#extension GL_NV_gpu_shader5 : require
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : require
|
|
||||||
|
|
||||||
#import <voxy:lod/nvmesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/block_model.glsl>
|
|
||||||
#import <voxy:lod/quad_format.glsl>
|
|
||||||
#line 13
|
|
||||||
|
|
||||||
layout(local_size_x = 16) in;
|
|
||||||
layout(triangles, max_vertices=64, max_primitives=32) out;
|
|
||||||
|
|
||||||
layout(location=1) out Interpolants {
|
|
||||||
vec2 uv;
|
|
||||||
} i_out[];
|
|
||||||
|
|
||||||
layout(location=2) perprimitiveNV out PerPrimData {
|
|
||||||
vec2 baseUV;
|
|
||||||
vec4 tinting;
|
|
||||||
vec4 addin;
|
|
||||||
uint flags;
|
|
||||||
vec4 conditionalTinting;
|
|
||||||
} per_prim_out[];
|
|
||||||
|
|
||||||
void emitIndicies() {
|
|
||||||
uint primBase = gl_LocalInvocationID.x * 6;
|
|
||||||
uint vertBase = gl_LocalInvocationID.x<<2;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+0] = vertBase+0;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+1] = vertBase+1;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+2] = vertBase+2;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+3] = vertBase+2;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+4] = vertBase+3;
|
|
||||||
gl_PrimitiveIndicesNV[primBase+5] = vertBase+0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 uint2vec4RGBA(uint colour) {
|
|
||||||
return vec4((uvec4(colour)>>uvec4(24,16,8,0))&uvec4(0xFF))/255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 getFaceSize(uint faceData) {
|
|
||||||
float EPSILON = 0.001f;
|
|
||||||
vec4 faceOffsetsSizes = extractFaceSizes(faceData);
|
|
||||||
//Expand the quads by a very small amount
|
|
||||||
faceOffsetsSizes.xz -= vec2(EPSILON);
|
|
||||||
faceOffsetsSizes.yw += vec2(EPSILON);
|
|
||||||
|
|
||||||
//Make the end relative to the start
|
|
||||||
faceOffsetsSizes.yw -= faceOffsetsSizes.xz;
|
|
||||||
|
|
||||||
return faceOffsetsSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: make branchless by using ternaries i think
|
|
||||||
vec3 swizzelDataAxis(uint axis, vec3 data) {
|
|
||||||
if (axis == 0) { //Up/down
|
|
||||||
data = data.xzy;
|
|
||||||
}
|
|
||||||
//Not needed, here for readability
|
|
||||||
//if (axis == 1) {//north/south
|
|
||||||
// offset = offset.xyz;
|
|
||||||
//}
|
|
||||||
if (axis == 2) { //west/east
|
|
||||||
data = data.zxy;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
taskNV in Task {
|
|
||||||
vec3 origin;//Offset to camera in world space (already multiplied by lod level)
|
|
||||||
uint baseOffset;//Base offset into the quad data buffer
|
|
||||||
|
|
||||||
uint meta;//First 4 bits is lod level, remaining is quadCount
|
|
||||||
};
|
|
||||||
|
|
||||||
uint getQuadIndex() {
|
|
||||||
if ((meta>>4)<=gl_GlobalInvocationID.x) return -1;
|
|
||||||
return baseOffset + gl_GlobalInvocationID.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint idx = getQuadIndex();
|
|
||||||
//If its over, dont render
|
|
||||||
if (idx == uint(-1)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emitIndicies();
|
|
||||||
|
|
||||||
uint A = gl_LocalInvocationID.x<<1;
|
|
||||||
uint B = (gl_LocalInvocationID.x<<1)|1u;
|
|
||||||
uint V = (gl_LocalInvocationID.x<<2);
|
|
||||||
|
|
||||||
uint lodLvl = meta&0xf;
|
|
||||||
float lodScale = (1<<lodLvl);
|
|
||||||
|
|
||||||
Quad quad = quadData[idx];
|
|
||||||
uint face = extractFace(quad);
|
|
||||||
uint modelId = extractStateId(quad);
|
|
||||||
BlockModel model = modelData[modelId];
|
|
||||||
uint faceData = model.faceData[face];
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
ivec2 quadSize = extractSize(quad);
|
|
||||||
|
|
||||||
|
|
||||||
//Compute the uv coordinates
|
|
||||||
vec2 modelUV = vec2(modelId&0xFFu, (modelId>>8)&0xFFu)*(1.0/(256.0));
|
|
||||||
vec2 baseUV = modelUV + (vec2(face>>1, face&1u) * (1.0/(vec2(3.0, 2.0)*256.0)));
|
|
||||||
//Write out baseUV
|
|
||||||
per_prim_out[A].baseUV = baseUV;
|
|
||||||
per_prim_out[B].baseUV = baseUV;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint flags = faceHasAlphaCuttout(faceData);
|
|
||||||
|
|
||||||
//We need to have a conditional override based on if the model size is < a full face + quadSize > 1
|
|
||||||
flags |= uint(any(greaterThan(quadSize, ivec2(1)))) & faceHasAlphaCuttoutOverride(faceData);
|
|
||||||
|
|
||||||
flags |= uint(!modelHasMipmaps(model))<<1;
|
|
||||||
|
|
||||||
//Compute lighting
|
|
||||||
vec4 tinting = getLighting(extractLightId(quad));
|
|
||||||
|
|
||||||
//Apply model colour tinting
|
|
||||||
uint tintColour = model.colourTint;
|
|
||||||
if (modelHasBiomeLUT(model)) {
|
|
||||||
tintColour = colourData[tintColour + extractBiomeId(quad)];
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 conditionalTinting = vec4(0);
|
|
||||||
if (tintColour != uint(-1)) {
|
|
||||||
flags |= 1u<<2;
|
|
||||||
conditionalTinting = uint2vec4RGBA(tintColour).yzwx;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 addin = vec4(0.0);
|
|
||||||
if (!isTranslucent) {
|
|
||||||
tinting.w = 0.0;
|
|
||||||
//Encode the face, the lod level and
|
|
||||||
uint encodedData = 0;
|
|
||||||
encodedData |= face;
|
|
||||||
encodedData |= (lodLvl<<3);
|
|
||||||
encodedData |= uint(hasAO)<<6;
|
|
||||||
addin.w = float(encodedData)/255.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply face tint
|
|
||||||
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) {
|
|
||||||
tinting.xyz *= 0.8f;
|
|
||||||
} else if ((face>>1) == 2) {
|
|
||||||
tinting.xyz *= 0.6f;
|
|
||||||
} else if (face == 0){
|
|
||||||
tinting.xyz *= 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Write out everything
|
|
||||||
per_prim_out[A].tinting = tinting;
|
|
||||||
per_prim_out[A].addin = addin;
|
|
||||||
per_prim_out[A].flags = flags;
|
|
||||||
per_prim_out[A].conditionalTinting = conditionalTinting;
|
|
||||||
per_prim_out[B].tinting = tinting;
|
|
||||||
per_prim_out[B].addin = addin;
|
|
||||||
per_prim_out[B].flags = flags;
|
|
||||||
per_prim_out[B].conditionalTinting = conditionalTinting;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vec4 faceSize = getFaceSize(faceData);
|
|
||||||
|
|
||||||
vec2 cQuadSize = faceSize.yw + quadSize - 1;
|
|
||||||
vec2 uv0 = faceSize.xz;
|
|
||||||
i_out[V|0].uv = uv0;
|
|
||||||
i_out[V|1].uv = uv0 + vec2(0, cQuadSize.y);
|
|
||||||
i_out[V|2].uv = uv0 + cQuadSize;
|
|
||||||
i_out[V|3].uv = uv0 + vec2(cQuadSize.x, 0);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Corner position of quad relative to section corner (in 0->32 scale)
|
|
||||||
vec3 cornerPos = extractPos(quad);
|
|
||||||
float depthOffset = extractFaceIndentation(faceData);
|
|
||||||
cornerPos += swizzelDataAxis(face>>1, vec3(faceSize.xz, mix(depthOffset, 1-depthOffset, float(face&1u))));
|
|
||||||
gl_MeshVerticesNV[V|0].gl_Position = MVP*vec4(cornerPos*lodScale+origin, 1.0);
|
|
||||||
gl_MeshVerticesNV[V|1].gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(0,cQuadSize.y,0)))*lodScale+origin, 1.0);
|
|
||||||
gl_MeshVerticesNV[V|2].gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(cQuadSize, 0)))*lodScale+origin, 1.0);
|
|
||||||
gl_MeshVerticesNV[V|3].gl_Position = MVP*vec4((cornerPos+swizzelDataAxis(face>>1,vec3(cQuadSize.x,0,0)))*lodScale+origin, 1.0);
|
|
||||||
|
|
||||||
if (gl_LocalInvocationID.x == 0) {
|
|
||||||
//Remaining quads in workgroup
|
|
||||||
gl_PrimitiveCountNV = min(uint(int(meta>>4)-int(gl_WorkGroupID.x<<4))<<1, 32);//2 primatives per quad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#version 460
|
|
||||||
|
|
||||||
#extension GL_ARB_shading_language_include : enable
|
|
||||||
#pragma optionNV(unroll all)
|
|
||||||
#define UNROLL_LOOP
|
|
||||||
|
|
||||||
#extension GL_NV_mesh_shader : require
|
|
||||||
#extension GL_NV_gpu_shader5 : require
|
|
||||||
#extension GL_ARB_gpu_shader_int64 : require
|
|
||||||
|
|
||||||
#import <voxy:lod/nvmesh/bindings.glsl>
|
|
||||||
#import <voxy:lod/section.glsl>
|
|
||||||
#line 12
|
|
||||||
|
|
||||||
#define MESH_WORKLOAD_PER_INVOCATION 16
|
|
||||||
|
|
||||||
layout(local_size_x=1) in;
|
|
||||||
|
|
||||||
taskNV out Task {
|
|
||||||
vec3 origin;//Offset to camera in world space (already multiplied by lod level)
|
|
||||||
uint baseOffset;//Base offset into the quad data buffer
|
|
||||||
uint meta;//First 4 bits is lod level, remaining is quadCount
|
|
||||||
} task;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint sectionId = gl_WorkGroupID.x;
|
|
||||||
bool visibleLastFrame = visibilityData[sectionId] == frameId;
|
|
||||||
|
|
||||||
//If it wasnt visible last frame then dont render this frame ** (do temporal coherance)
|
|
||||||
if (!visibleLastFrame) {
|
|
||||||
gl_TaskCountNV = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SectionMeta meta = sectionData[sectionId];
|
|
||||||
uint lodLvl = extractDetail(meta);
|
|
||||||
ivec3 lodPos= extractPosition(meta);
|
|
||||||
//Relative position to camera with resepct to lod level to check for visibility bits
|
|
||||||
ivec3 cpos = lodPos-(baseSectionPos>>lodLvl);
|
|
||||||
//Relative position to camera
|
|
||||||
task.origin = vec3(((lodPos<<lodLvl)-baseSectionPos)<<5)-cameraSubPos;
|
|
||||||
|
|
||||||
task.baseOffset = extractQuadStart(meta);
|
|
||||||
task.meta = lodLvl&0xFu;
|
|
||||||
|
|
||||||
uint cnt = meta.cntA&0xFFFF;//Skip translucency
|
|
||||||
|
|
||||||
task.meta |= cnt<<4;
|
|
||||||
gl_TaskCountNV = (cnt+MESH_WORKLOAD_PER_INVOCATION-1)/MESH_WORKLOAD_PER_INVOCATION;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user