voxel biomes and CPU pushed blocks

This commit is contained in:
Halbear 2026-09-20 17:57:19 +01:00
parent 7fda2614d7
commit a0b00b0f1c
24 changed files with 1007 additions and 91 deletions

View file

@ -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
}
}
}