#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; // A 1D storage buffer representing a flat 3D array of voxel IDs 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; int slot; uint faceOffset; uint unused0; uint indirectCommandIndex; uint biomeCount; }; float random3to1(vec3 st) { return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123); } float interpolate(float a, float b, float c, float d, float x) { float p = (d - c) - (a - b); return x * (x * (x * p + ((a - b) - p)) + (c - a)) + b; } float sampleX(vec3 at) { float floored = floor(at.x); return interpolate( random3to1(vec3(floored - 1.0, at.yz)), random3to1(vec3(floored, at.yz)), random3to1(vec3(floored + 1.0, at.yz)), random3to1(vec3(floored + 2.0, at.yz)), at.x - floored) * 0.5 + 0.25; } float sampleY(vec3 at) { float floored = floor(at.y); return interpolate( sampleX(vec3(at.x, floored - 1.0, at.z)), sampleX(vec3(at.x, floored, at.z)), sampleX(vec3(at.x, floored + 1.0, at.z)), sampleX(vec3(at.x, floored + 2.0, at.z)), at.y - floored); } float cubicNoise(vec3 at) { float floored = floor(at.z); return interpolate( sampleY(vec3(at.xy, floored - 1.0)), sampleY(vec3(at.xy, floored)), sampleY(vec3(at.xy, floored + 1.0)), sampleY(vec3(at.xy, floored + 2.0)), at.z - floored); } float rand(vec2 co) { return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453123); } float valueNoise(vec2 st) { vec2 i = floor(st); vec2 f = fract(st); float a = rand(i); float b = rand(i + vec2(1.0, 0.0)); float c = rand(i + vec2(0.0, 1.0)); float d = rand(i + vec2(1.0, 1.0)); vec2 u = f * f * (3.0 - 2.0 * f); return mix(a, b, u.x) + (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( 0.788675134594813, -0.211324865405187, -0.577350269189626, -0.211324865405187, 0.788675134594813, -0.577350269189626, 0.577350269189626, 0.577350269189626, 0.577350269189626) * X; float n = cubicNoise(X); return n > 0.5; } 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 + 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 * 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 = 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 = currentBiome.surfaceBlock; // Grass } else if (depthBelowSurface < 6.0) { voxelType = currentBiome.dirtBlock; // Dirt(also stone rn) } else { voxelType = currentBiome.stoneBlock; // Stone } } else{ float YZone2 = floor(worldPos.y/75.0)*75.0; float IslandUnderneathHeight2 = valueNoise(vec2(worldPos.x - YZone2 * 2, worldPos.z -YZone2 * 2) * 0.005) * 60 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 20 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 10+ valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2)) * 0.5 - 5 + YZone2; float height2 = valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.005) * 50 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.01) * 10 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 5+ valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2)) * 0.5 + YZone2; if (float(worldPos.y) <= height2 && float(worldPos.y) >= IslandUnderneathHeight2) { float depthBelowSurface = height2 - float(worldPos.y); if (depthBelowSurface < 0.5) { 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 = currentBiome.surfaceBlock; // Grass } else if (depthBelowSurface < 6.0) { voxelType = currentBiome.dirtBlock; // Dirt(also stone rn) } else { voxelType = currentBiome.stoneBlock; // Stone } } } if (voxelType != 0u) { if (isCave(vec3(worldPos*0.05))) { voxelType = 0u; } } uint index = uint((localPos.x * CHUNK_AREA) + (localPos.y * CHUNK_SIZE) + localPos.z); voxels[index] = voxelType; }