Terrain4J_Experimental_branch/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl

96 lines
No EOL
2.6 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 VERTICES_PER_FACE = 6u;
const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 6);
layout(std430, binding = 0) readonly buffer VoxelData {
uint voxels[];
};
layout(std430, binding = 1) buffer FaceBuffer {
uint faces[];
};
struct DrawCommand {
uint vertexCount;
uint instanceCount;
uint firstVertex;
uint firstInstance;
};
layout(std430, binding = 2) buffer DrawCommands {
DrawCommand drawCmds[];
};
layout(std430, binding = 3) buffer Counters {
uint faceCount;
} counters;
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int slot;
uint faceOffset;
uint unused0;
uint indirectCommandIndex;
uint 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 0u;
if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0u;
if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0u;
return voxels[flatten(pos)];
}
uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId, uint ao) {
return (voxelPos.x & 0x1Fu) |
((voxelPos.y & 0x1Fu) << 5u) |
((voxelPos.z & 0x1Fu) << 10u) |
((faceIndex & 0x7u) << 15u) |
((materialId & 0xFFu) << 18u) |
((ao & 0x3u) << 26u);
}
void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) {
uint localFace = atomicAdd(counters.faceCount, 1u);
if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) {
return;
}
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType, 0u);
atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_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, 0u, current);
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1u, current);
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2u, current);
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3u, current);
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4u, current);
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5u, current);
}