struct Params { origin: vec3; step: f32; }; @group(0) @binding(0) var params: Params; @group(0) @binding(1) var voxels: array; @group(0) @binding(2) var positions: array>; @group(0) @binding(3) var normals: array>; @group(0) @binding(4) var uvs: array>; @group(0) @binding(5) var indices: array; struct Counts { vertex: atomic; index: atomic; }; @group(0) @binding(6) var counts: Counts; const N: u32 = 16u; fn push_face(base: vec3, size: vec2, n: vec3, u: vec3, v: vec3) { let vi = atomicAdd(&counts.vertex, 4u); positions[vi + 0u] = base; positions[vi + 1u] = base + u * size.x; positions[vi + 2u] = base + u * size.x + v * size.y; positions[vi + 3u] = base + v * size.y; normals[vi + 0u] = n; normals[vi + 1u] = n; normals[vi + 2u] = n; normals[vi + 3u] = n; uvs[vi + 0u] = vec2(0.0, 1.0); uvs[vi + 1u] = vec2(1.0, 1.0); uvs[vi + 2u] = vec2(1.0, 0.0); uvs[vi + 3u] = vec2(0.0, 0.0); let ii = atomicAdd(&counts.index, 6u); if (n.x + n.y + n.z >= 0.0) { indices[ii + 0u] = vi; indices[ii + 1u] = vi + 1u; indices[ii + 2u] = vi + 2u; indices[ii + 3u] = vi + 2u; indices[ii + 4u] = vi + 3u; indices[ii + 5u] = vi; } else { indices[ii + 0u] = vi; indices[ii + 1u] = vi + 3u; indices[ii + 2u] = vi + 2u; indices[ii + 3u] = vi + 2u; indices[ii + 4u] = vi + 1u; indices[ii + 5u] = vi; } } @compute @workgroup_size(1,1,1) fn main(@builtin(global_invocation_id) gid: vec3) { if (gid.x > 0u) { return; } let s = params.step; for (var z: u32 = 0u; z < N; z = z + 1u) { for (var y: u32 = 0u; y < N; y = y + 1u) { for (var x: u32 = 0u; x < N; x = x + 1u) { let idx = z * N * N + y * N + x; if (voxels[idx] == 0u) { continue; } let base = params.origin + vec3(f32(x) * s, f32(y) * s, f32(z) * s); var filled: bool; // -X filled = false; if (x > 0u) { filled = voxels[idx - 1u] != 0u; } if (!filled) { push_face(base, vec2(s, s), vec3(-1.0,0.0,0.0), vec3(0.0,0.0,s), vec3(0.0,s,0.0)); } // +X filled = false; if (x + 1u < N) { filled = voxels[idx + 1u] != 0u; } if (!filled) { let b = base + vec3(s,0.0,0.0); push_face(b, vec2(s, s), vec3(1.0,0.0,0.0), vec3(0.0,s,0.0), vec3(0.0,0.0,s)); } // -Y filled = false; if (y > 0u) { filled = voxels[idx - N] != 0u; } if (!filled) { push_face(base, vec2(s, s), vec3(0.0,-1.0,0.0), vec3(s,0.0,0.0), vec3(0.0,0.0,s)); } // +Y filled = false; if (y + 1u < N) { filled = voxels[idx + N] != 0u; } if (!filled) { let b = base + vec3(0.0,s,0.0); push_face(b, vec2(s, s), vec3(0.0,1.0,0.0), vec3(0.0,0.0,s), vec3(s,0.0,0.0)); } // -Z filled = false; if (z > 0u) { filled = voxels[idx - N * N] != 0u; } if (!filled) { push_face(base, vec2(s, s), vec3(0.0,0.0,-1.0), vec3(s,0.0,0.0), vec3(0.0,s,0.0)); } // +Z filled = false; if (z + 1u < N) { filled = voxels[idx + N * N] != 0u; } if (!filled) { let b = base + vec3(0.0,0.0,s); push_face(b, vec2(s, s), vec3(0.0,0.0,1.0), vec3(s,0.0,0.0), vec3(0.0,s,0.0)); } } } } }