95 lines
3.1 KiB
GLSL
95 lines
3.1 KiB
GLSL
|
|
#[compute]
|
|
#version 450
|
|
|
|
// Workgroup size
|
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
|
|
// Storage buffer
|
|
layout(set = 0, binding = 0, std430) buffer DataBuffer {
|
|
float sample_points[];
|
|
} voxels;
|
|
|
|
layout(set = 0, binding = 1) uniform Params {
|
|
int world_size;
|
|
float threshold;
|
|
} params;
|
|
|
|
layout(set = 0, binding = 2, std430) buffer SurfaceBuffer {
|
|
float surface_points[];
|
|
} surface;
|
|
|
|
uint index3(uint x, uint y, uint z) {
|
|
return x + y * params.world_size + z * params.world_size * params.world_size;
|
|
}
|
|
|
|
void store_surface_point(uint idx, vec3 pos) {
|
|
uint base = idx * 3u;
|
|
surface.surface_points[base + 0u] = pos.x;
|
|
surface.surface_points[base + 1u] = pos.y;
|
|
surface.surface_points[base + 2u] = pos.z;
|
|
}
|
|
|
|
void main() {
|
|
uvec3 id = gl_GlobalInvocationID;
|
|
if (id.x >= uint(params.world_size) ||
|
|
id.y >= uint(params.world_size) ||
|
|
id.z >= uint(params.world_size))
|
|
return;
|
|
|
|
const ivec3 SURFACE_AXIS[8] = ivec3[](
|
|
ivec3(1,0,0),
|
|
ivec3(0,1,0),
|
|
ivec3(0,0,1),
|
|
ivec3(1,0,1),
|
|
ivec3(0,1,1),
|
|
ivec3(1,1,0),
|
|
ivec3(1,1,1),
|
|
ivec3(0,0,0)
|
|
);
|
|
|
|
vec3 p = vec3(id) - params.world_size / 2 + 1;
|
|
float d = length(p) - params.threshold;
|
|
uint idx = index3(id.x, id.y, id.z);
|
|
voxels.sample_points[idx] = d;
|
|
|
|
int previous_sign = 0;
|
|
vec3 previous_sample_point_coords = vec3(id.x, id.y, id.z);
|
|
float previous_sample_point_distance = 0.0;
|
|
vec3 intersection_points_sum = vec3(0.0, 0.0, 0.0);
|
|
uint intersection_points_count = 0u;
|
|
for (int sample_point_to_check_index = 0; sample_point_to_check_index < 8; sample_point_to_check_index++){
|
|
ivec3 sample_point_to_check = ivec3(id) + SURFACE_AXIS[sample_point_to_check_index];
|
|
|
|
// bounds check
|
|
if (sample_point_to_check.x < 0 || sample_point_to_check.y < 0 || sample_point_to_check.z < 0) continue;
|
|
if (uint(sample_point_to_check.x) >= params.world_size || uint(sample_point_to_check.y) >= params.world_size || uint(sample_point_to_check.z) >= params.world_size) continue;
|
|
|
|
uint buffer_index = index3(uint(sample_point_to_check.x), uint(sample_point_to_check.y), uint(sample_point_to_check.z));
|
|
float sample_point_distance_from_sdf = voxels.sample_points[buffer_index];
|
|
|
|
int current_sign = (sample_point_distance_from_sdf >= 0.0 ? 1 : -1);
|
|
|
|
if (previous_sign != 0 && current_sign != previous_sign) {
|
|
float t = previous_sample_point_distance / (previous_sample_point_distance - sample_point_distance_from_sdf);
|
|
vec3 intersect = mix(vec3(previous_sample_point_coords), vec3(sample_point_to_check), t);
|
|
intersection_points_sum += intersect;
|
|
intersection_points_count++;
|
|
}
|
|
|
|
previous_sign = current_sign;
|
|
previous_sample_point_distance = sample_point_distance_from_sdf;
|
|
previous_sample_point_coords = sample_point_to_check;
|
|
}
|
|
|
|
if (intersection_points_count > 0u) {
|
|
vec3 avg = intersection_points_sum / float(intersection_points_count);
|
|
store_surface_point(idx, avg);
|
|
} else {
|
|
store_surface_point(idx, vec3(0.0)); // no surface
|
|
}
|
|
|
|
|
|
|
|
}
|