87 lines
3.7 KiB
GLSL
87 lines
3.7 KiB
GLSL
#[compute]
|
|
#version 450
|
|
|
|
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
|
|
|
|
layout(set = 0, binding = 0, std430) buffer DataBuffer { float sample_points[]; } voxels;
|
|
layout(set = 0, binding = 1) uniform Params { int world_size; float threshold; float u_time; } params;
|
|
layout(set = 0, binding = 2, std430) buffer SurfaceBuffer { float surface_points[]; } surface;
|
|
layout(set = 0, binding = 5, std430) buffer IndexBuffer { uint indices[]; } mesh_indices;
|
|
layout(set = 0, binding = 6, std430) buffer Counter { uint count; } index_count;
|
|
|
|
uint index3(uint x, uint y, uint z) {
|
|
return x + y * params.world_size + z * params.world_size * params.world_size;
|
|
}
|
|
|
|
bool has_vertex(ivec3 p) {
|
|
// Boundary check for the voxel itself
|
|
if (any(lessThan(p, ivec3(0))) || any(greaterThanEqual(p, ivec3(params.world_size)))) return false;
|
|
uint idx = index3(uint(p.x), uint(p.y), uint(p.z));
|
|
return surface.surface_points[idx * 3u] > -0.5;
|
|
}
|
|
|
|
// Translated QUAD_POINTS from your GDScript
|
|
const ivec3 QUAD_OFFSETS[3][4] = ivec3[3][4](
|
|
// X-Axis Edges
|
|
ivec3[](ivec3(0,0,-1), ivec3(0,-1,-1), ivec3(0,-1,0), ivec3(0,0,0)),
|
|
// Y-Axis Edges
|
|
ivec3[](ivec3(0,0,-1), ivec3(0,0,0), ivec3(-1,0,0), ivec3(-1,0,-1)),
|
|
// Z-Axis Edges
|
|
ivec3[](ivec3(0,0,0), ivec3(0,-1,0), ivec3(-1,-1,0), ivec3(-1,0,0))
|
|
);
|
|
|
|
void main() {
|
|
ivec3 id = ivec3(gl_GlobalInvocationID);
|
|
if (id.x >= params.world_size || id.y >= params.world_size || id.z >= params.world_size) return;
|
|
|
|
uint idx = index3(id.x, id.y, id.z);
|
|
|
|
// Check the 3 primary axes (forward edges)
|
|
const ivec3 AXIS[3] = ivec3[](ivec3(1,0,0), ivec3(0,1,0), ivec3(0,0,1));
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
ivec3 neighbor_id = id + AXIS[i];
|
|
|
|
// Ensure neighbor is in bounds before sampling noise
|
|
if (any(greaterThanEqual(neighbor_id, ivec3(params.world_size)))) continue;
|
|
|
|
float d1 = voxels.sample_points[idx];
|
|
float d2 = voxels.sample_points[index3(neighbor_id.x, neighbor_id.y, neighbor_id.z)];
|
|
|
|
// Sign change check (Crossing detection)
|
|
if ((d1 < 0.0) != (d2 < 0.0)) {
|
|
ivec3 p0 = id + QUAD_OFFSETS[i][0];
|
|
ivec3 p1 = id + QUAD_OFFSETS[i][1];
|
|
ivec3 p2 = id + QUAD_OFFSETS[i][2];
|
|
ivec3 p3 = id + QUAD_OFFSETS[i][3];
|
|
|
|
// Verify all 4 surrounding voxels have valid vertices
|
|
if (has_vertex(p0) && has_vertex(p1) && has_vertex(p2) && has_vertex(p3)) {
|
|
uint v0 = index3(p0.x, p0.y, p0.z);
|
|
uint v1 = index3(p1.x, p1.y, p1.z);
|
|
uint v2 = index3(p2.x, p2.y, p2.z);
|
|
uint v3 = index3(p3.x, p3.y, p3.z);
|
|
|
|
uint start = atomicAdd(index_count.count, 6);
|
|
|
|
// Use the same winding logic as your add_quad / add_reversed_quad
|
|
if (d1 < 0.0) {
|
|
mesh_indices.indices[start + 0] = v0;
|
|
mesh_indices.indices[start + 1] = v1;
|
|
mesh_indices.indices[start + 2] = v2;
|
|
mesh_indices.indices[start + 3] = v0;
|
|
mesh_indices.indices[start + 4] = v2;
|
|
mesh_indices.indices[start + 5] = v3;
|
|
} else {
|
|
mesh_indices.indices[start + 0] = v0;
|
|
mesh_indices.indices[start + 1] = v2;
|
|
mesh_indices.indices[start + 2] = v1;
|
|
mesh_indices.indices[start + 3] = v0;
|
|
mesh_indices.indices[start + 4] = v3;
|
|
mesh_indices.indices[start + 5] = v2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|