mirror of
https://git.lynn.is/Gwen/pretty-automata.git
synced 2024-05-18 15:21:07 +02:00
104 lines
2.9 KiB
Plaintext
104 lines
2.9 KiB
Plaintext
#version 460
|
|
|
|
layout (local_size_x = 1, local_size_y = 1) in;
|
|
|
|
uniform uvec2 dimensions;
|
|
uniform uint birth_rule;
|
|
uniform uint survive_rule;
|
|
uniform uint starve_delay;
|
|
uniform bool starve_recover;
|
|
uniform bool has_max_age;
|
|
|
|
|
|
layout (std430) restrict readonly buffer buffer_data_in
|
|
{
|
|
uint data_in[];
|
|
};
|
|
layout (std430) restrict buffer buffer_data_out
|
|
{
|
|
uint data_out[];
|
|
};
|
|
|
|
#include "cellstate_common.glsl"
|
|
|
|
bool check_condition(uint rule, uint count) {
|
|
return ((rule >> count) & uint(1)) == 1;
|
|
}
|
|
|
|
void main() {
|
|
uint data_size = dimensions.x * dimensions.y;
|
|
uint neighbour_count = 0;
|
|
for (int ix = -1; ix < 2; ix++) {
|
|
for (int iy = -1; iy < 2; iy++) {
|
|
int cx = int(gl_GlobalInvocationID.x) + ix;
|
|
int cy = int(gl_GlobalInvocationID.y) + iy;
|
|
if (cx < 0) {
|
|
cx += int(dimensions.x);
|
|
} else if (cx >= dimensions.x) {
|
|
cx -= int(dimensions.x);
|
|
}
|
|
if (cy < 0) {
|
|
cy += int(dimensions.y);
|
|
} else if (cy >= dimensions.y) {
|
|
cy -= int(dimensions.y);
|
|
}
|
|
uint pos = cx + cy * dimensions.x;
|
|
neighbour_count += cellstate_from_data(data_in[pos]).alive ? 1 : 0;
|
|
}
|
|
}
|
|
|
|
uint pos = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * dimensions.x;
|
|
CellState state = cellstate_from_data(data_in[pos]);
|
|
uint max_age = data_in[data_size + pos];
|
|
|
|
|
|
if (state.alive) {
|
|
if (starve_recover) {
|
|
if (check_condition(birth_rule, neighbour_count)) {
|
|
state.starving = false;
|
|
} else {
|
|
if (state.starving) {
|
|
state.starve_duration = state.starve_duration + 1;
|
|
} else {
|
|
state.starving = true;
|
|
state.starve_duration = 0;
|
|
}
|
|
}
|
|
} else {
|
|
if (!check_condition(survive_rule, neighbour_count)) {
|
|
if (state.starving) {
|
|
state.starve_duration = state.starve_duration + 1;
|
|
} else {
|
|
state.starving = true;
|
|
state.starve_duration = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (has_max_age && state.age >= max_age) {
|
|
state.alive = false;
|
|
state.starving = false;
|
|
state.age = 0;
|
|
state.starve_duration = 0;
|
|
}
|
|
|
|
if (state.starving && state.starve_duration == starve_delay) {
|
|
state.starving = false;
|
|
state.alive = false;
|
|
state.age = 0;
|
|
state.starve_duration = 0;
|
|
} else {
|
|
state.age = state.age + 1;
|
|
}
|
|
} else {
|
|
if (check_condition(birth_rule, neighbour_count)) {
|
|
state.alive = true;
|
|
state.age = 0;
|
|
}
|
|
}
|
|
|
|
data_out[pos] = cellstate_to_data(state);
|
|
|
|
// propagate max-age
|
|
data_out[data_size + pos] = data_in[data_size + pos];
|
|
} |