God-Machine/Assets/Compute Shaders/automata.acompute
2025-08-10 22:55:53 -07:00

217 lines
No EOL
6.6 KiB
Text

#kernel Seed
#kernel Automaton
#kernel Blit
#extension GL_ARB_gpu_shader_int64 : require
layout(rgba8, set = 0, binding = 0) uniform image2D _RenderTarget;
layout(r16f, set = 0, binding = 2) uniform image2D _AutomatonFrom;
layout(r16f, set = 0, binding = 3) uniform image2D _AutomatonTo;
layout(binding = 1) uniform UniformBufferObject {
vec4 _Exposure;
};
layout(push_constant, std430) uniform Params {
vec2 raster_size;
vec2 seeds;
};
float pseudo(vec2 v) {
v = fract(v/128.)*128. + vec2(-64.340622, -72.465622);
return fract(dot(v.xyx * v.xyy, vec3(20.390625, 60.703125, 2.4281209)));
}
[numthreads(8, 8, 1)]
void Seed() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = ivec2(raster_size);
if (uv.x >= size.x || uv.y >= size.y) return;
float seed = pseudo(vec2(float(uv.x) * 0.1 + seeds.x, float(uv.y) * 0.1 + seeds.x * 3));
if (seed < 0.75) seed = 0.0;
else seed = 1.0;
imageStore(_AutomatonFrom, uv, vec4(seed));
}
[numthreads(8, 8, 1)]
void Automaton() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = ivec2(raster_size);
if (uv.x >= size.x || uv.y >= size.y) return;
int cell = int(imageLoad(_AutomatonFrom, uv).r);
uint64_t top_row_mask = 18374686479671623680UL;
uint64_t left_column_mask = 9259542123273814144UL;
uint64_t upper_left_mask = 770;
uint64_t upper_right_mask = 49216 & ~(left_column_mask);
uint64_t lower_left_mask = 144959613005987840UL & ~(top_row_mask);
uint64_t lower_right_mask = 4665729213955833856UL & ~(top_row_mask | left_column_mask);
uint neighbor_count = 0;
int neighborhood_radius = 1;
uint64_t upper_left_quadrant_bits = 0;
// Upper Left Quadrant
for (int y = -1; y <= 0; ++y) {
for (int x = -1; x <= 0; ++x) {
uint bit_index = -x + -y * 8; // Convert to 1D index in 64 bit uint
ivec2 world_coords = uv + ivec2(x, y);
uint64_t cell_value = int(imageLoad(_AutomatonFrom, world_coords % 512).r);
upper_left_quadrant_bits |= (cell_value << bit_index); // Shift cell value to bit index and add it to quadrant bit string
}
}
upper_left_quadrant_bits = upper_left_quadrant_bits & upper_left_mask; // Apply neighborhood mask
// Sum bits in string to get active cell count of quadrant
while (upper_left_quadrant_bits != 0) {
neighbor_count += uint(upper_left_quadrant_bits & 1);
upper_left_quadrant_bits = upper_left_quadrant_bits >> 1;
}
uint64_t upper_right_quadrant_bits = 0;
// Upper Right Quadrant
for (int y = -1; y <= 0; ++y) {
for (int x = 0; x <= 1; ++x) {
uint bit_index = (7 - x) + -y * 8; // Convert to 1D index in 64 bit uint
ivec2 world_coords = uv + ivec2(x, y);
uint64_t cell_value = int(imageLoad(_AutomatonFrom, world_coords % 512).r);
upper_right_quadrant_bits |= (cell_value << bit_index); // Shift cell value to bit index and add it to quadrant bit string
}
}
upper_right_quadrant_bits &= upper_right_mask;
// Sum bits in string to get active cell count of quadrant
while (upper_right_quadrant_bits != 0) {
neighbor_count += uint(upper_right_quadrant_bits & 1);
upper_right_quadrant_bits = upper_right_quadrant_bits >> 1;
}
uint64_t lower_left_quadrant_bits = 0;
// lower Left Quadrant
for (int y = 0; y <= 1; ++y) {
for (int x = -1; x <= 0; ++x) {
uint bit_index = -x + (7 - y) * 8; // Convert to 1D index in 64 bit uint
ivec2 world_coords = uv + ivec2(x, y);
uint64_t cell_value = int(imageLoad(_AutomatonFrom, world_coords % 512).r);
lower_left_quadrant_bits |= (cell_value << bit_index); // Shift cell value to bit index and add it to quadrant bit string
}
}
lower_left_quadrant_bits &= lower_left_mask;
// Sum bits in string to get active cell count of quadrant
while (lower_left_quadrant_bits != 0) {
neighbor_count += uint(lower_left_quadrant_bits & 1);
lower_left_quadrant_bits = lower_left_quadrant_bits >> 1;
}
uint64_t lower_right_quadrant_bits = 0;
// lower Right Quadrant
for (int y = 0; y <= 1; ++y) {
for (int x = 0; x <= 1; ++x) {
uint bit_index = (7 - x) + (7 - y) * 8; // Convert to 1D index in 64 bit uint
ivec2 world_coords = uv + ivec2(x, y);
uint64_t cell_value = int(imageLoad(_AutomatonFrom, world_coords % 512).r);
lower_right_quadrant_bits |= (cell_value << bit_index); // Shift cell value to bit index and add it to quadrant bit string
}
}
lower_right_quadrant_bits &= lower_right_mask;
// Sum bits in string to get active cell count of quadrant
while (lower_right_quadrant_bits != 0) {
neighbor_count += uint(lower_right_quadrant_bits & 1);
lower_right_quadrant_bits = lower_right_quadrant_bits >> 1;
}
// Upper Left
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2(-1, -1) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 0, -1) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2(-1, 0) % 512)).r);
// Upper Right
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 0, -1) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 1, -1) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 1, 0) % 512)).r);
// Center
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 0, 0) % 512)).r);
// Lower Left
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2(-1, 0) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2(-1, 1) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 0, 1) % 512)).r);
// Lower Right
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 1, 0) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 0, 1) % 512)).r);
// neighbor_count += uint(imageLoad(_AutomatonFrom, (uv + ivec2( 1, 1) % 512)).r);
// for (int x = -neighborhood_radius; x <= neighborhood_radius; ++x) {
// for (int y = -neighborhood_radius; y <= neighborhood_radius; ++y) {
// if (x == 0 && y == 0) continue;
// ivec2 texcoords = uv + ivec2(x, y);
// texcoords = texcoords % 512;
// neighbor_count += int(imageLoad(_AutomatonFrom, texcoords).r);
// }
// }
if (neighbor_count <= 1) cell = 0;
if (neighbor_count == 3) cell = 1;
if (neighbor_count >= 4) cell = 0;
// if (neighbor_count <= 33) cell = 0;
// if (34 <= neighbor_count && neighbor_count <= 45) cell = 1;
// if (58 <= neighbor_count && neighbor_count <= 121) cell = 0;
imageStore(_AutomatonTo, uv, vec4(cell));
}
[numthreads(8, 8, 1)]
void Blit() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = ivec2(raster_size);
if (uv.x >= size.x || uv.y >= size.y) return;
float automata = imageLoad(_AutomatonTo, uv / 2).r;
imageStore(_RenderTarget, uv, vec4(automata, 0, 0, 1.0));
}