const char *computeShaderSrc = R"glsl( #version 430 core layout (local_size_x = 1, local_size_y = 1) in; layout (rgba8) uniform writeonly image2D destTex; uniform sampler2D srcTex; uniform int X; uniform int Y; ivec2 wrapuv (ivec2 uv){ int wrapped_u = (uv.x % X + X) % X; int wrapped_v = (uv.y % Y + Y) % Y; return ivec2(wrapped_u, wrapped_v); } int alive(ivec2 uv){ uv = wrapuv(uv); vec4 px = texelFetch(srcTex,uv,0); return int(px.r > 0.5); } void main() { ivec2 uv = ivec2(gl_GlobalInvocationID.xy); vec4 c = texelFetch(srcTex,uv,0); int newState = alive(uv-ivec2(1,1)); imageStore(destTex, uv, vec4(newState, newState, newState, 1.0)); } )glsl"; const char *vertexShaderSrc = R"glsl( #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0); TexCoord = aTexCoord; } )glsl"; const char *fragmentShaderSrc = R"glsl( #version 330 core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D tex0; void main() { FragColor = texture(tex0, TexCoord); } )glsl"; float quadVertices[] = { 1.0f, 1.0f, 0.0f, /*top R*/ 1.0f, -1.0f, 0.0f, /*bottom R*/ -1.0f, -1.0f, 0.0f, /*bottom L*/ -1.0f, 1.0f, 0.0f /*top R*/ }; unsigned int quadIndices[] = { 0, 1, 3, /*tl triangle*/ 1, 2, 3 /*br triangle*/ };