214 lines
No EOL
7 KiB
GLSL
214 lines
No EOL
7 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;
|
|
|
|
struct Voxel {
|
|
uint MaterialIndex;
|
|
uint BlockType;
|
|
uvec2[2] UpIndex;
|
|
uvec2[2] DownIndex;
|
|
uvec2[2] NorthIndex;
|
|
uvec2[2] SouthIndex;
|
|
uvec2[2] EastIndex;
|
|
uvec2[2] WestIndex;
|
|
};
|
|
|
|
layout(std430, set = 1, binding = 0) readonly buffer VoxelUniform {
|
|
Voxel materials[];
|
|
} voxelReg;
|
|
|
|
layout(push_constant) uniform ChunkInfo {
|
|
ivec3 chunkPos;
|
|
int slot;
|
|
uint faceOffset;
|
|
uint voxelTypeCount;
|
|
uint indirectCommandIndex;
|
|
uint biomeCount;
|
|
uint structureCount;
|
|
uint worldSeed;
|
|
};
|
|
|
|
uint flatten(ivec3 pos) {
|
|
return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z);
|
|
}
|
|
bool isSeeThrough(Voxel voxel, uint type) {
|
|
if (type == 0u || voxel.BlockType == 3u || type > voxelTypeCount) return true;
|
|
return voxelReg.materials[type - 1u].BlockType >= 1u;
|
|
}
|
|
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 hash21(uvec2 p) {
|
|
p = p * 1664525u + 1013904223u;
|
|
p.x += p.y * 1664525u;
|
|
p.y += p.x * 1664525u;
|
|
return p.x ^ (p.x >> 16);
|
|
}
|
|
uint pcg_hash(uint seed) {
|
|
uint state = seed * 747796405u + 289133645u;
|
|
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
|
return (word >> 22u) ^ word;
|
|
}
|
|
|
|
uint randomRangeUint(uint seed, uint minVal, uint maxVal) {
|
|
uint range = maxVal - minVal + 1u;
|
|
return minVal + (pcg_hash(seed) % range);
|
|
}
|
|
uint random_1_to_3(vec2 uv, uint customSeed) {
|
|
uvec2 p = uvec2(floatBitsToUint(uv.x), floatBitsToUint(uv.y));
|
|
p.x ^= customSeed;
|
|
uint randInt = hash21(p);
|
|
return (randInt % 3u) + 1u;
|
|
}
|
|
|
|
uint packFace(uvec3 voxelPos, uint faceIndex, Voxel voxel) {
|
|
uint randomSeed = uint(voxelPos.x) * 73856093u ^ uint(voxelPos.z) * 19349663u;
|
|
uvec2 UpIndex = uvec2(randomRangeUint(randomSeed,voxel.UpIndex[0].x,voxel.UpIndex[1].x),randomRangeUint(randomSeed,voxel.UpIndex[0].y,voxel.UpIndex[1].y));
|
|
uvec2 DownIndex = uvec2(randomRangeUint(randomSeed,voxel.DownIndex[0].x,voxel.DownIndex[1].x),randomRangeUint(randomSeed,voxel.DownIndex[0].y,voxel.DownIndex[1].y));
|
|
uvec2 NorthIndex = uvec2(randomRangeUint(randomSeed,voxel.NorthIndex[0].x,voxel.NorthIndex[1].x),randomRangeUint(randomSeed,voxel.NorthIndex[0].y,voxel.NorthIndex[1].y));
|
|
uvec2 SouthIndex = uvec2(randomRangeUint(randomSeed,voxel.SouthIndex[0].x,voxel.SouthIndex[1].x),randomRangeUint(randomSeed,voxel.SouthIndex[0].y,voxel.SouthIndex[1].y));
|
|
uvec2 EastIndex = uvec2(randomRangeUint(randomSeed,voxel.EastIndex[0].x,voxel.EastIndex[1].x),randomRangeUint(randomSeed,voxel.EastIndex[0].y,voxel.EastIndex[1].y));
|
|
uvec2 WestIndex = uvec2(randomRangeUint(randomSeed,voxel.WestIndex[0].x,voxel.WestIndex[1].x),randomRangeUint(randomSeed,voxel.WestIndex[0].y,voxel.WestIndex[1].y));
|
|
|
|
uvec2 textureIndices[8] = uvec2[8](UpIndex, DownIndex, NorthIndex,
|
|
SouthIndex, EastIndex, WestIndex, NorthIndex,SouthIndex);
|
|
uvec2 tex = textureIndices[faceIndex];
|
|
uint textureIndexX = tex.x;
|
|
uint textureIndexY = tex.y;
|
|
uint materialId = voxel.MaterialIndex;
|
|
|
|
return (voxelPos.x & 0xFu) |
|
|
((voxelPos.y & 0xFu) << 4u) |
|
|
((voxelPos.z & 0xFu) << 8u) |
|
|
((faceIndex & 0x7u) << 12u) |
|
|
((materialId & 0x7FFu) << 15u) |
|
|
((textureIndexX & 0x7u) << 26u) |
|
|
((textureIndexY & 0x7u) << 29u);
|
|
}
|
|
|
|
uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId) {
|
|
uint randomFaceValue = random_1_to_3(vec2(voxelPos.x, voxelPos.z),faceOffset);
|
|
uint textureIndexX = 0u;
|
|
uint textureIndexY = 0u;
|
|
if(materialId == 1u){
|
|
if(faceIndex == 0u){
|
|
textureIndexX = 0u;
|
|
textureIndexY = randomFaceValue;
|
|
} else if(faceIndex == 1u){
|
|
textureIndexX = 1u;
|
|
textureIndexY = 0u;
|
|
}
|
|
else{
|
|
textureIndexX = 0u;
|
|
textureIndexY = 0u;
|
|
}
|
|
} else if(materialId == 2u){
|
|
textureIndexX = 1u;
|
|
textureIndexY = 0u;
|
|
}else if(materialId == 3u){
|
|
textureIndexX = 1u;
|
|
textureIndexY = 0u;
|
|
}else if(materialId == 4u){
|
|
textureIndexX = 1u;
|
|
textureIndexY = randomFaceValue;
|
|
}else if(materialId == 5u){
|
|
textureIndexX = 2u;
|
|
textureIndexY = 3u;
|
|
}else if(materialId == 5u){
|
|
if (faceIndex == 0u || faceIndex == 1u){
|
|
textureIndexX = 2u;
|
|
textureIndexY = 1u;
|
|
} else{
|
|
textureIndexX = 2u;
|
|
textureIndexY = 2u;
|
|
}
|
|
}else if(materialId == 6u){
|
|
textureIndexX = 2u;
|
|
textureIndexY = 0u;
|
|
}
|
|
|
|
return (voxelPos.x & 0xFu) |
|
|
((voxelPos.y & 0xFu) << 4u) |
|
|
((voxelPos.z & 0xFu) << 8u) |
|
|
((faceIndex & 0x7u) << 12u) |
|
|
((materialId & 0x7FFu) << 15u) |
|
|
((textureIndexX & 0x7u) << 26u) |
|
|
((textureIndexY & 0x7u) << 29u);
|
|
}
|
|
|
|
void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) {
|
|
if (voxelType == 0u || voxelType > voxelTypeCount) {
|
|
return;
|
|
}
|
|
|
|
uint localFace = atomicAdd(counters.faceCount, 1u);
|
|
|
|
if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) {
|
|
return;
|
|
}
|
|
|
|
Voxel voxel = voxelReg.materials[voxelType - 1u];
|
|
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxel);
|
|
|
|
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 || current > voxelTypeCount) {
|
|
return;
|
|
}
|
|
Voxel voxel = voxelReg.materials[current - 1u];
|
|
if (voxel.BlockType == 1u) {
|
|
emitFace(pos, 6u, current);
|
|
emitFace(pos, 7u, current);
|
|
return;
|
|
}
|
|
|
|
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 1, 0)))) emitFace(pos, 0u, current);
|
|
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, -1, 0)))) emitFace(pos, 1u, current);
|
|
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 1, 0, 0)))) emitFace(pos, 2u, current);
|
|
if (isSeeThrough(voxel,getVoxel(pos + ivec3(-1, 0, 0)))) emitFace(pos, 3u, current);
|
|
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 0, 1)))) emitFace(pos, 4u, current);
|
|
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 0, -1)))) emitFace(pos, 5u, current);
|
|
} |