#version 450
// Density field compute shader for Dual Contouring terrain.
// Template shader: the SDF body is injected at the GENERATOR_SDF_BODY marker
// by DCWorker at shader composition time.
//
// Each invocation computes one voxel corner density (and optionally normal).
layout(local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
// ---- Outputs ----
layout(set = 0, binding = 0, std430) buffer DensityBuf { float densities[]; };
layout(set = 0, binding = 1, std430) buffer NormalXBuf { float normal_x[]; };
layout(set = 0, binding = 2, std430) buffer NormalYBuf { float normal_y[]; };
layout(set = 0, binding = 3, std430) buffer NormalZBuf { float normal_z[]; };
// ---- Parameters (std140) ----
layout(set = 0, binding = 4, std140) uniform Params {
// Grid params (offset 0)
int grid_stride; // 0
float voxel_scale; // 4
float origin_x; // 8
float origin_y; // 12
float origin_z; // 16
// DensityConfig fields (offset 20)
float primary_frequency; // 20
float primary_strength; // 24
float tunnel_frequency; // 28
float tunnel_strength; // 32
float tunnel_radius; // 36
float ridge_frequency; // 40
float ridge_strength; // 44
float warp_frequency; // 48
float warp_strength; // 52
float detail_frequency; // 56
float detail_strength; // 60
float ground_bias; // 64
float solid_floor_depth; // 68
float sky_height; // 72
float flat_center_radius; // 76
float floor_strength; // 80
float floor_height_min; // 84
float floor_height_max; // 88
float room_height; // 92
float terrain_size; // 96
// Pre-computed octave counts (offset 100)
int primary_octaves; // 100
int tunnel_octaves; // 104
int ridge_octaves; // 108
int warp_octaves; // 112
int detail_octaves; // 116
// Flags (offset 120)
int compute_normals; // 120
int seed; // 124
int voronoi_cell_count; // 128
int use_noise; // 132
// Spherical mode
int spherical; // 136 — 1 = planet mode
float planet_radius; // 140
float planet_center_x; // 144
float planet_center_y; // 148
float planet_center_z; // 152
float island_radius; // 156
};
// ---- Voronoi cells: count followed by (x, z, floor_height) triples ----
layout(set = 0, binding = 5, std430) buffer VoronoiBuf {
int voronoi_count;
float voronoi_data[]; // [x0, z0, h0, x1, z1, h1, ...]
};
// ---- Permutation tables: 6 x 512 ints ----
// Order: primary, tunnel_a, tunnel_b, ridge, warp, detail
layout(set = 0, binding = 6, std430) buffer PermBuf {
int perm_tables[]; // 3072 entries total
};
// ---- CSG primitives ----
struct CSGPrimitive {
uint prim_type; // 0=sphere, 1=box
uint op; // 0=union, 1=subtract, 2=intersect
uint group;
uint flags; // bit 0 = is_first_in_group
float pos_x, pos_y, pos_z;
float _pad0;
float size_x, size_y, size_z; // half_extents for box, radius in size_x for sphere
float _pad1;
};
layout(set = 0, binding = 7, std430) readonly buffer CSGBuf {
uint csg_count;
uint _csg_pad[3];
CSGPrimitive csg_primitives[];
};
// =====================================================================
// SDF body — injected by DCWorker from generator GLSL
// Must define: float evaluate_density(float x, float y, float z)
// =====================================================================
// GENERATOR_SDF_BODY
// =====================================================================
// Main
// =====================================================================
void main() {
uvec3 gid = gl_GlobalInvocationID;
int stride = grid_stride;
if (int(gid.x) >= stride || int(gid.y) >= stride || int(gid.z) >= stride)
return;
int idx = int(gid.z) * stride * stride + int(gid.y) * stride + int(gid.x);
float wx = origin_x + float(gid.x) * voxel_scale;
float wy = origin_y + float(gid.y) * voxel_scale;
float wz = origin_z + float(gid.z) * voxel_scale;
float d = evaluate_density(wx, wy, wz);
densities[idx] = d;
// Optionally compute normals via tetrahedron gradient (same as DensityGrid::gradient)
if (compute_normals != 0) {
float h = voxel_scale * 2.0;
float d0 = evaluate_density(wx + h, wy - h, wz - h);
float d1 = evaluate_density(wx - h, wy - h, wz + h);
float d2 = evaluate_density(wx - h, wy + h, wz - h);
float d3 = evaluate_density(wx + h, wy + h, wz + h);
// Negate for outward-facing normals (density positive = solid)
float nx = -(d0 - d1 - d2 + d3);
float ny = -(-d0 - d1 + d2 + d3);
float nz = -(-d0 + d1 - d2 + d3);
float len = sqrt(nx * nx + ny * ny + nz * nz);
if (len > 1e-10) {
nx /= len; ny /= len; nz /= len;
}
normal_x[idx] = nx;
normal_y[idx] = ny;
normal_z[idx] = nz;
}
}