OverviewFilesCommitsIssuesDocsReleasesPeers

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

159 lines · glsl ref:
#version 450

// ============================================================================
// Stage 5: Surface Normals
//
// Template shader: the SDF body is injected at the GENERATOR_SDF_BODY marker
// by DCWorker at shader composition time.
//
// For each active edge intersection, compute the gradient of the density
// field at the intersection point via central differences using the full
// density evaluation function.
//
// Input:
//   density[]      — density grid (unused by noise SDF, used by grid SDF)
//   edge_data[]    — position set by Stage 4
//   Params UBO     — density evaluation parameters
//   voronoi_data[] — voronoi cell data
//   perm_tables[]  — noise permutation tables
//   csg_primitives — CSG primitive list
//   counts[]       — counts[0] = active edge count
//
// Output:
//   edge_data[active].normal — updated with normalized gradient
//
// Dispatch: ceil(active_count / 256), 1, 1
// ============================================================================

#define THREADS 256

layout(local_size_x = THREADS, local_size_y = 1, local_size_z = 1) in;

layout(set = 0, binding = 0, std430) readonly buffer DensityBuf { float density[]; };
layout(set = 0, binding = 3, std430)          buffer EdgeData   { float edge_data[]; };

// Density evaluation parameters (same layout as edge_intersect.glsl)
layout(set = 0, binding = 4, std140) uniform Params {
    int   grid_stride;
    float voxel_scale;
    float origin_x;
    float origin_y;
    float origin_z;
    float primary_frequency;
    float primary_strength;
    float tunnel_frequency;
    float tunnel_strength;
    float tunnel_radius;
    float ridge_frequency;
    float ridge_strength;
    float warp_frequency;
    float warp_strength;
    float detail_frequency;
    float detail_strength;
    float ground_bias;
    float solid_floor_depth;
    float sky_height;
    float flat_center_radius;
    float floor_strength;
    float floor_height_min;
    float floor_height_max;
    float room_height;
    float terrain_size;
    int primary_octaves;
    int tunnel_octaves;
    int ridge_octaves;
    int warp_octaves;
    int detail_octaves;
    int compute_normals;
    int seed;
    int voronoi_cell_count;
    int use_noise;
    int spherical;
    float planet_radius;
    float planet_center_x;
    float planet_center_y;
    float planet_center_z;
    float island_radius;
};

layout(set = 0, binding = 5, std430) readonly buffer VoronoiBuf {
    int   voronoi_count;
    float voronoi_data[];
};

layout(set = 0, binding = 6, std430) readonly buffer PermBuf {
    int perm_tables[];
};

// CSG primitives
struct CSGPrimitive {
    uint  prim_type;
    uint  op;
    uint  group;
    uint  flags;
    float pos_x, pos_y, pos_z;
    float _pad0;
    float size_x, size_y, size_z;
    float _pad1;
};

layout(set = 0, binding = 7, std430) readonly buffer CSGBuf {
    uint csg_count;
    uint _csg_pad[3];
    CSGPrimitive csg_primitives[];
};

layout(set = 0, binding = 8, std430) readonly buffer CountBuf { uint counts[]; };

layout(push_constant) uniform PushConstants {
    vec3  cell_origin;
    float voxel_size;
    ivec3 grid_dims;
    uint  total_elements;
    uint  mesh_quality_flags;
    uint  _pc_pad0;
    uint  _pc_pad1;
    uint  _pc_pad2;
};

// =====================================================================
// SDF body — injected by DCWorker from generator GLSL
// Must define: float evaluate_density(float x, float y, float z)
// =====================================================================
// GENERATOR_SDF_BODY

// =====================================================================
// Main: compute normals via central differences on the full SDF
// =====================================================================

void main() {
    uint gid = gl_GlobalInvocationID.x;
    uint active_count = counts[0];
    if (gid >= active_count) return;

    uint base = gid * 8u;

    // Read world-space position (set by edge_intersect)
    float wx = edge_data[base + 0u];
    float wy = edge_data[base + 1u];
    float wz = edge_data[base + 2u];

    // Central differences on the full SDF
    float eps = voxel_size * 0.01;
    vec3 n;
    n.x = evaluate_density(wx + eps, wy, wz) - evaluate_density(wx - eps, wy, wz);
    n.y = evaluate_density(wx, wy + eps, wz) - evaluate_density(wx, wy - eps, wz);
    n.z = evaluate_density(wx, wy, wz + eps) - evaluate_density(wx, wy, wz - eps);

    float len = length(n);
    if (len > 1e-8) {
        n /= len;
    } else {
        n = vec3(0.0, 1.0, 0.0);  // fallback
    }

    edge_data[base + 3u] = n.x;
    edge_data[base + 4u] = n.y;
    edge_data[base + 5u] = n.z;
}