#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]; }