voxel biomes and CPU pushed blocks
This commit is contained in:
parent
7fda2614d7
commit
a0b00b0f1c
24 changed files with 1007 additions and 91 deletions
|
|
@ -32,11 +32,26 @@ 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 unused0;
|
||||
uint voxelTypeCount;
|
||||
uint indirectCommandIndex;
|
||||
uint padding0;
|
||||
};
|
||||
|
|
@ -44,7 +59,10 @@ layout(push_constant) uniform ChunkInfo {
|
|||
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;
|
||||
|
|
@ -58,7 +76,16 @@ uint hash21(uvec2 p) {
|
|||
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;
|
||||
|
|
@ -66,6 +93,31 @@ uint random_1_to_3(vec2 uv, uint customSeed) {
|
|||
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;
|
||||
|
|
@ -107,23 +159,28 @@ uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId) {
|
|||
textureIndexY = 0u;
|
||||
}
|
||||
|
||||
return (voxelPos.x & 0x1Fu) |
|
||||
((voxelPos.y & 0x1Fu) << 5u) |
|
||||
((voxelPos.z & 0x1Fu) << 10u) |
|
||||
((faceIndex & 0x7u) << 15u) |
|
||||
((materialId & 0xFFu) << 18u) |
|
||||
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;
|
||||
}
|
||||
|
||||
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType);
|
||||
Voxel voxel = voxelReg.materials[voxelType - 1u];
|
||||
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxel);
|
||||
|
||||
atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_PER_FACE);
|
||||
}
|
||||
|
|
@ -136,21 +193,20 @@ void main() {
|
|||
}
|
||||
|
||||
uint current = getVoxel(pos);
|
||||
|
||||
if (current == 0u) {
|
||||
if (current == 0u || current > voxelTypeCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (current == 4u) {
|
||||
Voxel voxel = voxelReg.materials[current - 1u];
|
||||
if (voxel.BlockType == 1u) {
|
||||
emitFace(pos, 6u, current);
|
||||
emitFace(pos, 7u, current);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u || getVoxel(pos + ivec3( 0, 1, 0)) == 4u) emitFace(pos, 0u, current);
|
||||
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u || getVoxel(pos + ivec3( 0, -1, 0)) == 4u) emitFace(pos, 1u, current);
|
||||
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u || getVoxel(pos + ivec3( 1, 0, 0)) == 4u) emitFace(pos, 2u, current);
|
||||
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u || getVoxel(pos + ivec3( -1, 0, 0)) == 4u) emitFace(pos, 3u, current);
|
||||
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u|| getVoxel(pos + ivec3( 0, 0, 1)) == 4u) emitFace(pos, 4u, current);
|
||||
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u || getVoxel(pos + ivec3( 0, 0, -1)) == 4u) emitFace(pos, 5u, current);
|
||||
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);
|
||||
}
|
||||
|
|
@ -8,6 +8,19 @@ const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
|
|||
layout(std430, binding = 0) buffer VoxelData {
|
||||
uint voxels[];
|
||||
};
|
||||
struct Biome {
|
||||
uint surfaceBlock;
|
||||
uint dirtBlock;
|
||||
uint stoneBlock;
|
||||
uint grassFoliage;
|
||||
uint[4] flowers;
|
||||
uint[4] tallBlocks;
|
||||
uint[4] otherFoliage;
|
||||
};
|
||||
|
||||
layout(std430, set = 1, binding = 0) readonly buffer BiomeUniform {
|
||||
Biome biomes[];
|
||||
} BiomeReg;
|
||||
|
||||
layout(push_constant) uniform ChunkInfo {
|
||||
ivec3 chunkPos;
|
||||
|
|
@ -15,15 +28,8 @@ layout(push_constant) uniform ChunkInfo {
|
|||
uint faceOffset;
|
||||
uint unused0;
|
||||
uint indirectCommandIndex;
|
||||
uint padding0;
|
||||
uint biomeCount;
|
||||
};
|
||||
vec3 random3(vec3 st) {
|
||||
return fract(sin(vec3(
|
||||
dot(st, vec3(127.1, 311.7, 74.7)),
|
||||
dot(st, vec3(269.5, 183.3, 246.1)),
|
||||
dot(st, vec3(113.5, 271.9, 124.6))
|
||||
)) * 43758.5453123);
|
||||
}
|
||||
|
||||
float random3to1(vec3 st) {
|
||||
return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123);
|
||||
|
|
@ -88,6 +94,29 @@ float valueNoise(vec2 st) {
|
|||
(c - a) * u.y * (1.0 - u.x) +
|
||||
(d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
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 GetBiome(vec3 worldPos, uint MaxBiomes) {
|
||||
if (MaxBiomes == 0u) return 0u;
|
||||
vec3 X = vec3(worldPos);
|
||||
X = mat3(
|
||||
0.788675134594813, -0.211324865405187, -0.577350269189626,
|
||||
-0.211324865405187, 0.788675134594813, -0.577350269189626,
|
||||
0.577350269189626, 0.577350269189626, 0.577350269189626) * X;
|
||||
float n = clamp(cubicNoise(X), 0.0, 0.9999);
|
||||
uint Biome = uint(floor(n * float(MaxBiomes)));
|
||||
return min(Biome, MaxBiomes - 1u);
|
||||
}
|
||||
bool isCave(vec3 worldPos) {
|
||||
vec3 X = vec3(worldPos);
|
||||
X = mat3(
|
||||
|
|
@ -101,33 +130,41 @@ bool isCave(vec3 worldPos) {
|
|||
void main() {
|
||||
ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz);
|
||||
ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos;
|
||||
|
||||
|
||||
uint biome = GetBiome(vec3(worldPos.z, worldPos.y, worldPos.x) * 0.05, biomeCount);
|
||||
Biome currentBiome = BiomeReg.biomes[biome];
|
||||
|
||||
float YZone = floor(worldPos.y/150.0)*150.0;
|
||||
float SurfaceHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 +
|
||||
float SurfaceHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 +
|
||||
|
||||
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.01) * 10 +
|
||||
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 5 +
|
||||
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2)) * 0.5 + YZone;
|
||||
|
||||
uint RandomBlockVal = randomRangeUint(uint(worldPos.x) * 73856093u ^ uint(worldPos.z) * 19349663u,0u ,3u);
|
||||
float IslandUnderneathHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 +
|
||||
|
||||
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 20 +
|
||||
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 5 +
|
||||
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2)) * 0.5 - 15 + YZone;
|
||||
|
||||
float grassNoise = valueNoise(vec2(worldPos.z + YZone * 2, worldPos.x + YZone * 2));
|
||||
float grassNoise = valueNoise(vec2(worldPos.z * 0.5 - YZone * 2, worldPos.x * 0.5 - YZone * 2));
|
||||
|
||||
uint voxelType = 0u;
|
||||
|
||||
if (float(worldPos.y) <= SurfaceHeight && float(worldPos.y) >= IslandUnderneathHeight) {
|
||||
float depthBelowSurface = SurfaceHeight - float(worldPos.y);
|
||||
if (depthBelowSurface < 0.5) {
|
||||
if(grassNoise < 0.65) voxelType = 4u; // Grass foliage
|
||||
if(grassNoise < 0.65) voxelType = currentBiome.grassFoliage; // Grass foliage
|
||||
else if (grassNoise < 0.75) voxelType = currentBiome.flowers[RandomBlockVal];
|
||||
else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[RandomBlockVal];
|
||||
else voxelType = 0u;
|
||||
}else if (depthBelowSurface < 2.5) {
|
||||
voxelType = 1u; // Grass
|
||||
voxelType = currentBiome.surfaceBlock; // Grass
|
||||
} else if (depthBelowSurface < 6.0) {
|
||||
voxelType = 2u; // Dirt(also stone rn)
|
||||
voxelType = currentBiome.dirtBlock; // Dirt(also stone rn)
|
||||
} else {
|
||||
voxelType = 3u; // Stone
|
||||
voxelType = currentBiome.stoneBlock; // Stone
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
|
@ -145,14 +182,16 @@ void main() {
|
|||
float depthBelowSurface = height2 - float(worldPos.y);
|
||||
|
||||
if (depthBelowSurface < 0.5) {
|
||||
if (grassNoise < 0.65) voxelType = 4u; // Grass foliage
|
||||
if (grassNoise < 0.65) voxelType = currentBiome.grassFoliage; // Grass foliage
|
||||
else if (grassNoise < 0.75) voxelType = currentBiome.flowers[RandomBlockVal];
|
||||
else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[RandomBlockVal];
|
||||
else voxelType = 0u;
|
||||
} else if (depthBelowSurface < 1.5) {
|
||||
voxelType = 1u; // Grass
|
||||
voxelType = currentBiome.surfaceBlock; // Grass
|
||||
} else if (depthBelowSurface < 6.0) {
|
||||
voxelType = 2u; // Dirt(also stone rn)
|
||||
voxelType = currentBiome.dirtBlock; // Dirt(also stone rn)
|
||||
} else {
|
||||
voxelType = 3u; // Stone
|
||||
voxelType = currentBiome.stoneBlock; // Stone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue