236 lines
No EOL
6.5 KiB
GLSL
236 lines
No EOL
6.5 KiB
GLSL
#version 460
|
|
|
|
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
|
|
|
|
const int CHUNK_SIZE = 16;
|
|
const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
|
|
const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
|
|
|
|
const uint FLOATS_PER_VERTEX = 14u;
|
|
const uint INTEGERS_PER_VERTEX = 1u;
|
|
const uint VERTICES_PER_FACE = 4u;
|
|
const uint INDICES_PER_FACE = 6u;
|
|
|
|
const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * 12);
|
|
const uint MAX_VERTICES = MAX_VISIBLE_FACES_PER_CHUNK * VERTICES_PER_FACE;
|
|
const uint MAX_INDICES = MAX_VISIBLE_FACES_PER_CHUNK * INDICES_PER_FACE;
|
|
|
|
layout(std430, binding = 0) readonly buffer VoxelData {
|
|
uint voxels[];
|
|
};
|
|
|
|
layout(std430, binding = 1) buffer VertexBuffer {
|
|
float vertices[];
|
|
};
|
|
|
|
layout(std430, binding = 2) buffer IndexBuffer {
|
|
uint indices[];
|
|
};
|
|
|
|
layout(std430, binding = 3) buffer DrawCommand {
|
|
uint indexCount;
|
|
uint instanceCount;
|
|
uint firstIndex;
|
|
int vertexOffset;
|
|
uint firstInstance;
|
|
} drawCmd;
|
|
|
|
layout(std430, binding = 4) buffer Counters {
|
|
uint vertexCount;
|
|
uint indexCount;
|
|
} counters;
|
|
|
|
layout(push_constant) uniform ChunkInfo {
|
|
ivec3 chunkPos;
|
|
int padding0;
|
|
};
|
|
|
|
uint flatten(ivec3 pos) {
|
|
return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z);
|
|
}
|
|
|
|
uint getVoxel(ivec3 pos) {
|
|
if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0;
|
|
if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0;
|
|
if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0;
|
|
|
|
return voxels[flatten(pos)];
|
|
}
|
|
|
|
void writeVertex(uint vertexIndex,vec3 position,vec3 normal,
|
|
vec3 tangent,vec3 bitangent,vec2 uv) {
|
|
uint base = vertexIndex * FLOATS_PER_VERTEX;
|
|
|
|
vertices[base + 0u] = position.x;
|
|
vertices[base + 1u] = position.y;
|
|
vertices[base + 2u] = position.z;
|
|
|
|
vertices[base + 3u] = normal.x;
|
|
vertices[base + 4u] = normal.y;
|
|
vertices[base + 5u] = normal.z;
|
|
|
|
vertices[base + 6u] = tangent.x;
|
|
vertices[base + 7u] = tangent.y;
|
|
vertices[base + 8u] = tangent.z;
|
|
|
|
vertices[base + 9u] = bitangent.x;
|
|
vertices[base + 10u] = bitangent.y;
|
|
vertices[base + 11u] = bitangent.z;
|
|
|
|
vertices[base + 12u] = uv.x;
|
|
vertices[base + 13u] = uv.y;
|
|
}
|
|
|
|
void emitFace(ivec3 voxelPos, int faceIndex) {
|
|
uint baseVertex = atomicAdd(counters.vertexCount, VERTICES_PER_FACE);
|
|
uint baseIndex = atomicAdd(counters.indexCount, INDICES_PER_FACE);
|
|
|
|
if (baseVertex + VERTICES_PER_FACE > MAX_VERTICES ||
|
|
baseIndex + INDICES_PER_FACE > MAX_INDICES) {
|
|
return;
|
|
}
|
|
|
|
vec3 p = vec3(voxelPos);
|
|
|
|
vec3 normal;
|
|
vec3 tangent;
|
|
vec3 bitangent;
|
|
|
|
vec3 v0;
|
|
vec3 v1;
|
|
vec3 v2;
|
|
vec3 v3;
|
|
|
|
vec2 uv0;
|
|
vec2 uv1;
|
|
vec2 uv2;
|
|
vec2 uv3;
|
|
|
|
if (faceIndex == 0) {
|
|
// Top +Y
|
|
normal = vec3(0.0, 1.0, 0.0);
|
|
tangent = vec3(1.0, 0.0, 0.0);
|
|
bitangent = vec3(0.0, 0.0, 1.0);
|
|
|
|
v0 = p + vec3(0.0, 1.0, 0.0);
|
|
v1 = p + vec3(0.0, 1.0, 1.0);
|
|
v2 = p + vec3(1.0, 1.0, 1.0);
|
|
v3 = p + vec3(1.0, 1.0, 0.0);
|
|
|
|
|
|
uv0 = vec2(0.0, 0.5);
|
|
uv1 = vec2(0.0, 1.0);
|
|
uv2 = vec2(0.5, 1.0);
|
|
uv3 = vec2(0.5, 0.5);
|
|
} else if (faceIndex == 1) {
|
|
// Bottom -Y
|
|
normal = vec3(0.0, -1.0, 0.0);
|
|
tangent = vec3(1.0, 0.0, 0.0);
|
|
bitangent = vec3(0.0, 0.0, -1.0);
|
|
|
|
v0 = p + vec3(0.0, 0.0, 0.0);
|
|
v1 = p + vec3(1.0, 0.0, 0.0);
|
|
v2 = p + vec3(1.0, 0.0, 1.0);
|
|
v3 = p + vec3(0.0, 0.0, 1.0);
|
|
uv0 = vec2(0.5, 0.0);
|
|
uv1 = vec2(0.5, 0.5);
|
|
uv2 = vec2(1.0, 0.5);
|
|
uv3 = vec2(1.0, 0.0);
|
|
} else if (faceIndex == 2) {
|
|
// Right +X
|
|
normal = vec3(1.0, 0.0, 0.0);
|
|
tangent = vec3(0.0, 0.0, -1.0);
|
|
bitangent = vec3(0.0, 1.0, 0.0);
|
|
|
|
v0 = p + vec3(1.0, 0.0, 0.0);
|
|
v1 = p + vec3(1.0, 1.0, 0.0);
|
|
v2 = p + vec3(1.0, 1.0, 1.0);
|
|
v3 = p + vec3(1.0, 0.0, 1.0);
|
|
|
|
uv0 = vec2(0.0, 0.0);
|
|
uv3 = vec2(0.0, 0.5);
|
|
uv2 = vec2(0.5, 0.5);
|
|
uv1 = vec2(0.5, 0.0);
|
|
} else if (faceIndex == 3) {
|
|
// Left -X
|
|
normal = vec3(-1.0, 0.0, 0.0);
|
|
tangent = vec3(0.0, 0.0, 1.0);
|
|
bitangent = vec3(0.0, 1.0, 0.0);
|
|
|
|
v0 = p + vec3(0.0, 0.0, 0.0);
|
|
v1 = p + vec3(0.0, 0.0, 1.0);
|
|
v2 = p + vec3(0.0, 1.0, 1.0);
|
|
v3 = p + vec3(0.0, 1.0, 0.0);
|
|
|
|
uv0 = vec2(0.0, 0.0);
|
|
uv1 = vec2(0.0, 0.5);
|
|
uv2 = vec2(0.5, 0.5);
|
|
uv3 = vec2(0.5, 0.0);
|
|
} else if (faceIndex == 4) {
|
|
// Front +Z
|
|
normal = vec3(0.0, 0.0, 1.0);
|
|
tangent = vec3(1.0, 0.0, 0.0);
|
|
bitangent = vec3(0.0, 1.0, 0.0);
|
|
|
|
v0 = p + vec3(0.0, 0.0, 1.0);
|
|
v1 = p + vec3(1.0, 0.0, 1.0);
|
|
v2 = p + vec3(1.0, 1.0, 1.0);
|
|
v3 = p + vec3(0.0, 1.0, 1.0);
|
|
|
|
uv0 = vec2(0.0, 0.0);
|
|
uv1 = vec2(0.0, 0.5);
|
|
uv2 = vec2(0.5, 0.5);
|
|
uv3 = vec2(0.5, 0.0);
|
|
} else {
|
|
// Back -Z
|
|
normal = vec3(0.0, 0.0, -1.0);
|
|
tangent = vec3(-1.0, 0.0, 0.0);
|
|
bitangent = vec3(0.0, 1.0, 0.0);
|
|
|
|
v0 = p + vec3(0.0, 0.0, 0.0);
|
|
v1 = p + vec3(0.0, 1.0, 0.0);
|
|
v2 = p + vec3(1.0, 1.0, 0.0);
|
|
v3 = p + vec3(1.0, 0.0, 0.0);
|
|
|
|
uv0 = vec2(0.0, 0.0);
|
|
uv1 = vec2(0.0, 0.5);
|
|
uv2 = vec2(0.5, 0.5);
|
|
uv3 = vec2(0.5, 0.0);
|
|
}
|
|
|
|
writeVertex(baseVertex + 0u, v0, normal, tangent, bitangent, uv0);
|
|
writeVertex(baseVertex + 1u, v1, normal, tangent, bitangent, uv1);
|
|
writeVertex(baseVertex + 2u, v2, normal, tangent, bitangent, uv2);
|
|
writeVertex(baseVertex + 3u, v3, normal, tangent, bitangent, uv3);
|
|
|
|
indices[baseIndex + 0u] = baseVertex + 0u;
|
|
indices[baseIndex + 1u] = baseVertex + 1u;
|
|
indices[baseIndex + 2u] = baseVertex + 2u;
|
|
|
|
indices[baseIndex + 3u] = baseVertex + 0u;
|
|
indices[baseIndex + 4u] = baseVertex + 2u;
|
|
indices[baseIndex + 5u] = baseVertex + 3u;
|
|
|
|
atomicAdd(drawCmd.indexCount, INDICES_PER_FACE);
|
|
}
|
|
|
|
void main() {
|
|
ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
|
|
|
|
if (pos.x >= CHUNK_SIZE || pos.y >= CHUNK_SIZE || pos.z >= CHUNK_SIZE) {
|
|
return;
|
|
}
|
|
|
|
uint current = getVoxel(pos);
|
|
|
|
if (current == 0u) {
|
|
return;
|
|
}
|
|
|
|
if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0);
|
|
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1);
|
|
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2);
|
|
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3);
|
|
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4);
|
|
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5);
|
|
} |