i did a little memory optimisation (19GB of VRAM -> 2.6GB of VRAM), lost some FPS in vertex rendering as a result but i'll figure it out

This commit is contained in:
Halbear 2026-09-16 20:38:37 +01:00
parent bf9af81f38
commit ce7051d8ca
21 changed files with 766 additions and 592 deletions

View file

@ -7,6 +7,7 @@ const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
const uint FLOATS_PER_VERTEX = 14u;
const uint INTEGERS_PER_VERTEX = 1u;
const uint VERTICES_PER_FACE = 4u;
const uint INDICES_PER_FACE = 6u;
@ -89,13 +90,12 @@ void emitFace(ivec3 voxelPos, int faceIndex) {
return;
}
vec3 p = vec3(chunkPos * CHUNK_SIZE + voxelPos);
vec3 p = vec3(voxelPos);
vec3 normal;
vec3 tangent;
vec3 bitangent;
vec3 v0;
vec3 v1;
vec3 v2;

View file

@ -6,261 +6,72 @@ 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 FLOATS_PER_VERTEX = 14u;
const uint VERTICES_PER_FACE = 4u;
const uint INDICES_PER_FACE = 6u;
const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * 12);
const uint MAX_VERTICES = MAX_VISIBLE_FACES_PER_CHUNK * VERTICES_PER_FACE;
const uint MAX_INDICES = MAX_VISIBLE_FACES_PER_CHUNK * INDICES_PER_FACE;
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 VertexBuffer {
float vertices[];
};
layout(std430, binding = 2) buffer IndexBuffer {
uint indices[];
layout(std430, binding = 1) buffer FaceBuffer {
uint faces[];
};
struct DrawCommand {
uint indexCount;
uint vertexCount;
uint instanceCount;
uint firstIndex;
int vertexOffset;
uint firstVertex;
uint firstInstance;
};
layout(std430, binding = 3) buffer DrawCommands {
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 vertexFloatOffset;
uint indexOffset;
uint faceOffset;
uint unused0;
uint indirectCommandIndex;
uint padding0;
};
layout(std430, binding = 4) buffer Counters {
uint vertexCount;
uint indexCount;
} counters;
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 0;
if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0;
if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0;
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)];
}
void writeVertex(uint vertexIndex, vec3 position, vec3 normal, vec3 tangent, vec3 bitangent, vec2 uv) {
uint base = vertexFloatOffset + vertexIndex * FLOATS_PER_VERTEX;
vertices[base + 0u] = position.x;
vertices[base + 1u] = position.y;
vertices[base + 2u] = position.z;
vertices[base + 3u] = normal.x;
vertices[base + 4u] = normal.y;
vertices[base + 5u] = normal.z;
vertices[base + 6u] = tangent.x;
vertices[base + 7u] = tangent.y;
vertices[base + 8u] = tangent.z;
vertices[base + 9u] = bitangent.x;
vertices[base + 10u] = bitangent.y;
vertices[base + 11u] = bitangent.z;
vertices[base + 12u] = uv.x;
vertices[base + 13u] = uv.y;
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, int faceIndex, uint VoxelType) {
uint localBaseVertex = atomicAdd(counters.vertexCount, VERTICES_PER_FACE);
uint localBaseIndex = atomicAdd(counters.indexCount, INDICES_PER_FACE);
void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) {
uint localFace = atomicAdd(counters.faceCount, 1u);
if (localBaseVertex + VERTICES_PER_FACE > MAX_VERTICES ||
localBaseIndex + INDICES_PER_FACE > MAX_INDICES) {
if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) {
return;
}
uint baseVertex = localBaseVertex;
uint baseIndex = indexOffset + localBaseIndex;
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType, 0u);
vec3 p = vec3(chunkPos * CHUNK_SIZE + voxelPos);
vec3 normal;
vec3 tangent;
vec3 bitangent;
vec3 v0;
vec3 v1;
vec3 v2;
vec3 v3;
vec2 uv0;
vec2 uv1;
vec2 uv2;
vec2 uv3;
if (faceIndex == 0) {
// Top +Y
normal = vec3(0.0, 1.0, 0.0);
tangent = vec3(1.0, 0.0, 0.0);
bitangent = vec3(0.0, 0.0, 1.0);
v0 = p + vec3(0.0, 1.0, 0.0);
v1 = p + vec3(0.0, 1.0, 1.0);
v2 = p + vec3(1.0, 1.0, 1.0);
v3 = p + vec3(1.0, 1.0, 0.0);
if(VoxelType == 1) {
uv0 = vec2(0.0, 0.5);
uv1 = vec2(0.0, 1.0);
uv2 = vec2(0.5, 1.0);
uv3 = vec2(0.5, 0.5);
} else{
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
}
} else if (faceIndex == 1) {
// Bottom -Y
normal = vec3(0.0, -1.0, 0.0);
tangent = vec3(1.0, 0.0, 0.0);
bitangent = vec3(0.0, 0.0, -1.0);
v0 = p + vec3(0.0, 0.0, 0.0);
v1 = p + vec3(1.0, 0.0, 0.0);
v2 = p + vec3(1.0, 0.0, 1.0);
v3 = p + vec3(0.0, 0.0, 1.0);
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
} else if (faceIndex == 2) {
// Right +X
normal = vec3(1.0, 0.0, 0.0);
tangent = vec3(0.0, 0.0, -1.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(1.0, 0.0, 0.0);
v1 = p + vec3(1.0, 1.0, 0.0);
v2 = p + vec3(1.0, 1.0, 1.0);
v3 = p + vec3(1.0, 0.0, 1.0);
if(VoxelType == 1) {
uv2 = vec2(0.0, 0.0);
uv3 = vec2(0.0, 0.5);
uv0 = vec2(0.5, 0.5);
uv1 = vec2(0.5, 0.0);
} else{
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
}
} else if (faceIndex == 3) {
// Left -X
normal = vec3(-1.0, 0.0, 0.0);
tangent = vec3(0.0, 0.0, 1.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(0.0, 0.0, 0.0);
v1 = p + vec3(0.0, 0.0, 1.0);
v2 = p + vec3(0.0, 1.0, 1.0);
v3 = p + vec3(0.0, 1.0, 0.0);
if(VoxelType == 1) {
uv3 = vec2(0.0, 0.0);
uv0 = vec2(0.0, 0.5);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(0.5, 0.0);
} else{
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
}
} else if (faceIndex == 4) {
// Front +Z
normal = vec3(0.0, 0.0, 1.0);
tangent = vec3(1.0, 0.0, 0.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(0.0, 0.0, 1.0);
v1 = p + vec3(1.0, 0.0, 1.0);
v2 = p + vec3(1.0, 1.0, 1.0);
v3 = p + vec3(0.0, 1.0, 1.0);
if(VoxelType == 1) {
uv3 = vec2(0.0, 0.0);
uv0 = vec2(0.0, 0.5);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(0.5, 0.0);
} else{
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
}
} else {
// Back -Z
normal = vec3(0.0, 0.0, -1.0);
tangent = vec3(-1.0, 0.0, 0.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(0.0, 0.0, 0.0);
v1 = p + vec3(0.0, 1.0, 0.0);
v2 = p + vec3(1.0, 1.0, 0.0);
v3 = p + vec3(1.0, 0.0, 0.0);
if(VoxelType == 1) {
uv2 = vec2(0.0, 0.0);
uv3 = vec2(0.0, 0.5);
uv0 = vec2(0.5, 0.5);
uv1 = vec2(0.5, 0.0);
} else{
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
}
}
writeVertex(baseVertex + 0u, v0, normal, tangent, bitangent, uv0);
writeVertex(baseVertex + 1u, v1, normal, tangent, bitangent, uv1);
writeVertex(baseVertex + 2u, v2, normal, tangent, bitangent, uv2);
writeVertex(baseVertex + 3u, v3, normal, tangent, bitangent, uv3);
indices[baseIndex + 0u] = baseVertex + 0u;
indices[baseIndex + 1u] = baseVertex + 1u;
indices[baseIndex + 2u] = baseVertex + 2u;
indices[baseIndex + 3u] = baseVertex + 0u;
indices[baseIndex + 4u] = baseVertex + 2u;
indices[baseIndex + 5u] = baseVertex + 3u;
atomicAdd(drawCmds[indirectCommandIndex].indexCount, INDICES_PER_FACE);
atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_PER_FACE);
}
void main() {
@ -276,10 +87,10 @@ void main() {
return;
}
if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0,current);
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1,current);
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2,current);
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3,current);
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4,current);
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5,current);
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);
}

View file

@ -2,13 +2,10 @@
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
const uint FLOATS_PER_VERTEX = 14u;
struct DrawCommand {
uint indexCount;
uint vertexCount;
uint instanceCount;
uint firstIndex;
int vertexOffset;
uint firstVertex;
uint firstInstance;
};
@ -17,26 +14,23 @@ layout(std430, binding = 0) buffer DrawCommands {
};
layout(std430, binding = 1) buffer Counters {
uint vertexCount;
uint indexCount;
uint faceCount;
} counters;
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int slot;
uint vertexFloatOffset;
uint indexOffset;
uint faceOffset;
uint unused0;
uint indirectCommandIndex;
uint padding0;
};
void main() {
drawCmds[indirectCommandIndex].indexCount = 0u;
drawCmds[indirectCommandIndex].vertexCount = 0u;
drawCmds[indirectCommandIndex].instanceCount = 1u;
drawCmds[indirectCommandIndex].firstIndex = indexOffset;
drawCmds[indirectCommandIndex].vertexOffset = int(vertexFloatOffset / FLOATS_PER_VERTEX);
drawCmds[indirectCommandIndex].firstVertex = faceOffset * 6u;
drawCmds[indirectCommandIndex].firstInstance = 0u;
counters.vertexCount = 0u;
counters.indexCount = 0u;
counters.faceCount = 0u;
}

View file

@ -9,187 +9,70 @@ layout(std430, binding = 0) buffer VoxelData {
uint voxels[];
};
layout(push_constant) uniform ChunkOffset {
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int slot;
uint vertexFloatOffset;
uint indexOffset;
uint faceOffset;
uint unused0;
uint indirectCommandIndex;
uint padding0;
};
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : stegu
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com
vec4 permute(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); }
vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
float simplex_noise(vec3 v) {
const vec2 C = vec2(1.0/6.0, 1.0/3.0);
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy));
vec3 x0 = v - i + dot(i, C.xxx);
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min(g.xyz, l.zxy);
vec3 i2 = max(g.xyz, l.zxy);
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod(i, 289.0);
vec4 p = permute(permute(permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_); // mod(j,N)
vec4 x = x_ * ns.x + ns.yyyy;
vec4 y = y_ * ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4(x.xy, y.xy);
vec4 b1 = vec4(x.zw, y.zw);
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0) * 2.0 + 1.0;
vec4 s1 = floor(b1) * 2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
vec3 p0 = vec3(a0.xy, h.x);
vec3 p1 = vec3(a0.zw, h.y);
vec3 p2 = vec3(a1.xy, h.z);
vec3 p3 = vec3(a1.zw, h.w);
// Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
// Returns a value scaled exactly between -1.0 and 1.0
return 42.0 * dot(m * m, vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3)));
}
float noise2D(vec2 p) {
return simplex_noise(vec3(p.x, p.y, 0.0));
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 fbm(vec2 p, int octaves, float lacunarity, float gain) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
float amplitudeSum = 0.0;
for (int i = 0; i < octaves; i++) {
value += noise2D(p * frequency) * amplitude;
amplitudeSum += amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return value / amplitudeSum;
float random3to1(vec3 st) {
return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123);
}
float ridgedFbm(vec2 p, int octaves, float lacunarity, float gain) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
float amplitudeSum = 0.0;
float interpolate(float a, float b, float c, float d, float x) {
float p = (d - c) - (a - b);
for (int i = 0; i < octaves; i++) {
float n = noise2D(p * frequency);
n = 1.0 - abs(n);
n = n * n;
value += n * amplitude;
amplitudeSum += amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return value / amplitudeSum;
return x * (x * (x * p + ((a - b) - p)) + (c - a)) + b;
}
vec2 domainWarp(vec2 p) {
float wx = fbm(p + vec2(17.31, 91.73), 3, 2.0, 0.5);
float wz = fbm(p + vec2(43.17, 12.89), 3, 2.0, 0.5);
float sampleX(vec3 at) {
float floored = floor(at.x);
return p + vec2(wx, wz) * 35.0;
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 terrainHeight(vec2 worldXZ) {
vec2 p = worldXZ;
float sampleY(vec3 at) {
float floored = floor(at.y);
vec2 warped = domainWarp(p * 0.004);
float broad = fbm(warped * 0.45, 5, 2.0, 0.5);
broad = broad * 0.5 + 0.5;
float hills = fbm(p * 0.025, 4, 2.0, 0.48);
float detail = fbm(p * 0.085, 2, 2.0, 0.4);
float height = 8.0;
height += broad * 12.0;
height += hills * 6.0;
height += detail * 2.0;
return clamp(height, 4.0, 28.0);
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 fbm3D(vec3 p, int octaves, float lacunarity, float gain) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
float amplitudeSum = 0.0;
for (int i = 0; i < octaves; i++) {
value += simplex_noise(p * frequency) * amplitude;
amplitudeSum += amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return value / amplitudeSum;
}
float valueNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
@ -205,37 +88,29 @@ float valueNoise(vec2 st) {
(c - a) * u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
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);
vec2 randG(vec2 p) {
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
return n > 0.5;
}
float perlinNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
float dotTopLeft = dot(randG(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0));
float dotTopRight = dot(randG(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0));
float dotBottomLeft = dot(randG(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0));
float dotBottomRight = dot(randG(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0));
return mix(mix(dotTopLeft, dotTopRight, u.x),
mix(dotBottomLeft, dotBottomRight, u.x), u.y);
}
void main() {
ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz);
ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos;
float height = valueNoise(vec2(worldPos.x, worldPos.z) * 0.005) * 100 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.01) * 10 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5;
//height = clamp(height, 4.0, 28.0);
float islandheight = valueNoise(vec2(worldPos.z, worldPos.x) * 0.005) * 100 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 20 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5 - 15;
float height = valueNoise(vec2(worldPos.x, worldPos.z) * 0.005) * 100 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.01) * 10 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5;
float height2 = valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.005) * 100 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.01) * 10 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.1) * 5+ valueNoise(vec2(-worldPos.x, -worldPos.z)) * 0.5 + 100;
float islandheight2 = 100 + valueNoise(vec2(-worldPos.z, -worldPos.x) * 0.005) * 100 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.1) * 20 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5 - 5;
//height = clamp(height, 4.0, 28.0);
uint voxelType = 0u;
if (float(worldPos.y) <= height && float(floor(worldPos.y/CHUNK_SIZE) * CHUNK_SIZE + CHUNK_SIZE * 2) >= height) {
if (float(worldPos.y) <= height && float(worldPos.y) >= islandheight) {
float depthBelowSurface = height - float(worldPos.y);
if (depthBelowSurface < 1.5) {
@ -246,14 +121,23 @@ void main() {
voxelType = 3u; // Stone
}
}
if(float(worldPos.y) <= height2 && float(worldPos.y) >= islandheight2){
float depthBelowSurface = height2 - float(worldPos.y);
// if (voxelType != 0u && worldPos.y < int(height) - 6) {
// float cave = fbm3D(vec3(worldPos) * 0.045, 4, 2.0, 0.5);
//
// if (cave > 0.42) {
// voxelType = 0u;
// }
// }
if (depthBelowSurface < 1.5) {
voxelType = 1u; // Grass/topsoil
} else if (depthBelowSurface < 5.0) {
voxelType = 2u; // Dirt
} else {
voxelType = 3u; // 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;

View file

@ -0,0 +1,96 @@
#version 450
layout(location = 0) in uint inPackedVertex;
layout(location = 0) out vec4 outPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec3 outTangent;
layout(location = 3) out vec3 outBitangent;
layout(location = 4) out vec2 outTextCoords;
layout(location = 5) out mat4 viewMatrix;
const vec3 NORMALS[6] = vec3[6](
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, -1.0, 0.0),
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0),
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0)
);
const vec3 TANGENTS[6] = vec3[6](
vec3( 1.0, 0.0, 0.0),
vec3( 1.0, 0.0, 0.0),
vec3( 0.0, 0.0, -1.0),
vec3( 0.0, 0.0, 1.0),
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0)
);
const vec3 BITANGENTS[6] = vec3[6](
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0)
);
const vec2 CORNER_UVS[16] = vec2[16](
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0),
vec2(0.0, 0.5),
vec2(0.0, 1.0),
vec2(0.5, 1.0),
vec2(0.5, 0.5),
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0),
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0)
);
layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform;
layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform;
layout(push_constant) uniform pc {
vec4 ModelOffset;
vec4 Padding0;
vec4 Padding1;
vec4 Padding2;
} push_constants;
void main() {
viewMatrix = viewUniform.matrix;
uint posX = inPackedVertex & 0x1Fu;
uint posY = (inPackedVertex >> 5u) & 0x1Fu;
uint posZ = (inPackedVertex >> 10u) & 0x1Fu;
uint faceIdx = (inPackedVertex >> 15u) & 0x7u;
uint cornerIdx = (inPackedVertex >> 18u) & 0x3u;
uint matId = (inPackedVertex >> 20u) & 0xFFu;
vec3 inPos = vec3(posX, posY, posZ) + push_constants.ModelOffset.xyz * 16.0;
vec3 inNormal = NORMALS[faceIdx];
vec3 inTangent = TANGENTS[faceIdx];
vec3 inBitangent = BITANGENTS[faceIdx];
vec2 inTextCoords = CORNER_UVS[cornerIdx + 4 * matId];
vec4 worldPos = vec4(inPos, 1.0);
gl_Position = projUniform.matrix * viewUniform.matrix * worldPos;
outPos = worldPos;
outNormal = inNormal;
outTangent = inTangent;
outBitangent = inBitangent;
outTextCoords = inTextCoords;
}

View file

@ -0,0 +1,149 @@
#version 450
layout(location = 0) out vec4 outPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec3 outTangent;
layout(location = 3) out vec3 outBitangent;
layout(location = 4) out vec2 outTextCoords;
layout(location = 5) out mat4 viewMatrix;
layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform;
layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform;
layout(set = 4, binding = 0) readonly buffer FaceBuffer {
uint faces[];
};
layout(push_constant) uniform pc {
vec4 ModelOffset;
vec4 Padding0;
vec4 Padding1;
vec4 Padding2;
} push_constants;
const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u);
const vec3 NORMALS[6] = vec3[6](
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, -1.0, 0.0),
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0),
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0)
);
const vec3 TANGENTS[6] = vec3[6](
vec3( 1.0, 0.0, 0.0),
vec3( 1.0, 0.0, 0.0),
vec3( 0.0, 0.0, -1.0),
vec3( 0.0, 0.0, 1.0),
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0)
);
const vec3 BITANGENTS[6] = vec3[6](
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0)
);
const vec2 CORNER_UVS[16] = vec2[16](
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0),
vec2(0.0, 0.5),
vec2(0.0, 1.0),
vec2(0.5, 1.0),
vec2(0.5, 0.5),
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0),
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0)
);
vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) {
vec3 p = vec3(voxelPos);
if (faceId == 0u) {
if (cornerIndex == 0u) return p + vec3(0.0, 1.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 1.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(1.0, 1.0, 0.0);
}
if (faceId == 1u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 0.0, 1.0);
return p + vec3(0.0, 0.0, 1.0);
}
if (faceId == 2u) {
if (cornerIndex == 0u) return p + vec3(1.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(1.0, 1.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(1.0, 0.0, 1.0);
}
if (faceId == 3u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 0.0, 1.0);
if (cornerIndex == 2u) return p + vec3(0.0, 1.0, 1.0);
return p + vec3(0.0, 1.0, 0.0);
}
if (faceId == 4u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 1.0);
if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 1.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(0.0, 1.0, 1.0);
}
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 0.0);
return p + vec3(1.0, 0.0, 0.0);
}
void main() {
viewMatrix = viewUniform.matrix;
uint faceRecordIndex = uint(gl_VertexIndex) / 6u;
uint triangleVertex = uint(gl_VertexIndex) % 6u;
uint cornerIndex = TRI_TO_CORNER[triangleVertex];
uint packedFace = faces[faceRecordIndex];
uint voxelX = packedFace & 0x1Fu;
uint voxelY = (packedFace >> 5u) & 0x1Fu;
uint voxelZ = (packedFace >> 10u) & 0x1Fu;
uint faceId = (packedFace >> 15u) & 0x7u;
uint matId = (packedFace >> 18u) & 0xFFu;
faceId = min(faceId, 5u);
matId = min(matId, 3u);
vec3 localPos = buildFaceCornerPosition(uvec3(voxelX, voxelY, voxelZ), faceId, cornerIndex);
vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0;
vec4 worldPosVec4 = vec4(worldPos, 1.0);
gl_Position = projUniform.matrix * viewUniform.matrix * worldPosVec4;
outPos = worldPosVec4;
outNormal = NORMALS[faceId];
outTangent = TANGENTS[faceId];
outBitangent = BITANGENTS[faceId];
outTextCoords = CORNER_UVS[cornerIndex + 4u * matId];
}

View file

@ -0,0 +1,84 @@
#version 450
layout(set = 3, binding = 0) readonly buffer FaceBuffer {
uint faces[];
};
layout(push_constant) uniform matrices {
vec4 ModelOffset;
vec4 Padding0;
vec4 Padding1;
vec4 Padding2;
uint materialIdx;
} push_constants;
layout(location = 0) out vec2 outTextCoord;
layout(location = 1) out flat uint outMaterialIdx;
const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u);
vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) {
vec3 p = vec3(voxelPos);
if (faceId == 0u) {
if (cornerIndex == 0u) return p + vec3(0.0, 1.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 1.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(1.0, 1.0, 0.0);
}
if (faceId == 1u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 0.0, 1.0);
return p + vec3(0.0, 0.0, 1.0);
}
if (faceId == 2u) {
if (cornerIndex == 0u) return p + vec3(1.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(1.0, 1.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(1.0, 0.0, 1.0);
}
if (faceId == 3u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 0.0, 1.0);
if (cornerIndex == 2u) return p + vec3(0.0, 1.0, 1.0);
return p + vec3(0.0, 1.0, 0.0);
}
if (faceId == 4u) {
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 1.0);
if (cornerIndex == 1u) return p + vec3(1.0, 0.0, 1.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 1.0);
return p + vec3(0.0, 1.0, 1.0);
}
if (cornerIndex == 0u) return p + vec3(0.0, 0.0, 0.0);
if (cornerIndex == 1u) return p + vec3(0.0, 1.0, 0.0);
if (cornerIndex == 2u) return p + vec3(1.0, 1.0, 0.0);
return p + vec3(1.0, 0.0, 0.0);
}
void main() {
uint faceRecordIndex = uint(gl_VertexIndex) / 6u;
uint triangleVertex = uint(gl_VertexIndex) % 6u;
uint cornerIndex = TRI_TO_CORNER[triangleVertex];
uint packedFace = faces[faceRecordIndex];
uint voxelX = packedFace & 0x1Fu;
uint voxelY = (packedFace >> 5u) & 0x1Fu;
uint voxelZ = (packedFace >> 10u) & 0x1Fu;
uint faceId = (packedFace >> 15u) & 0x7u;
uint matId = (packedFace >> 18u) & 0xFFu;
vec3 localPos = buildFaceCornerPosition(uvec3(voxelX, voxelY, voxelZ), faceId, cornerIndex);
vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0;
outTextCoord = vec2(0.0);
outMaterialIdx = matId;
gl_Position = vec4(worldPos, 1.0);
}