OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / distribute / hypertps-win64 / shaders / edge_classify.glsl

62 lines · glsl ref:
#version 450

// Edge classification compute shader for Dual Contouring terrain (Stage 2).
// For each voxel in the 32³ grid, check 3 edges (+X, +Y, +Z) for sign changes
// in the density field produced by Stage 1 (density_fill).
//
// A sign change on an edge means the isosurface crosses that edge,
// which will later require a vertex placement (QEF solve).

#define THREADS 256

layout(local_size_x = THREADS) in;

// ---- Buffers ----
layout(set = 0, binding = 0, std430) readonly  buffer DensityBuf   { float density[];    };
layout(set = 0, binding = 1, std430) writeonly buffer EdgeFlagBuf  { uint  edge_flags[];  };

// ---- Push constants ----
layout(push_constant) uniform PushConstants {
    vec3  cell_origin;    //  0: world-space origin of this chunk
    float voxel_size;     // 12: size of one voxel in world units
    ivec3 grid_dims;      // 16: voxel grid dimensions (32, 32, 32)
    uint  total_elements;
    uint  mesh_quality_flags;
    uint  _pc_pad0;
    uint  _pc_pad1;
    uint  _pc_pad2;
};

// Density grid is (V+1)³ where V = grid_dims.x (= 32), so stride = 33.
// density index: z * S * S + y * S + x  where S = grid_dims.x + 1

void main() {
    uint gid = gl_GlobalInvocationID.x;
    if (gid >= total_elements)
        return;

    int V = grid_dims.x;           // 32
    int S = V + 1;                 // 33 (density grid stride)

    // Decode linear voxel index to (x, y, z)
    int z = int(gid) / (V * V);
    int y = (int(gid) % (V * V)) / V;
    int x = int(gid) % V;

    // Density at corner (x, y, z)
    float d0 = density[z * S * S + y * S + x];

    // Check 3 edges for sign changes
    // Edge 0: +X direction  (x, y, z) -> (x+1, y, z)
    float dx = density[z * S * S + y * S + (x + 1)];
    edge_flags[gid * 3u + 0u] = ((d0 >= 0.0) != (dx >= 0.0)) ? 1u : 0u;

    // Edge 1: +Y direction  (x, y, z) -> (x, y+1, z)
    float dy = density[z * S * S + (y + 1) * S + x];
    edge_flags[gid * 3u + 1u] = ((d0 >= 0.0) != (dy >= 0.0)) ? 1u : 0u;

    // Edge 2: +Z direction  (x, y, z) -> (x, y, z+1)
    float dz = density[(z + 1) * S * S + y * S + x];
    edge_flags[gid * 3u + 2u] = ((d0 >= 0.0) != (dz >= 0.0)) ? 1u : 0u;
}