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); int state = alive(uv); int cnt = 0; for(int y = -1; y <= 1; ++y) for(int x = -1; x <= 1; ++x){ if(x == 0 && y == 0) continue; cnt += alive((uv + ivec2(x,y))); } int newState = ((state == 1 && (cnt == 2 || cnt == 3)) || (state == 0 && cnt == 3)) ? 1 : 0; 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 + vec2(1,1); } )glsl"; const char *fragmentShaderSrc = R"glsl( #version 330 core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D tex0; void main() { FragColor = texture(tex0, TexCoord/vec2(2,2)); } )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*/ };