void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = fragCoord/iResolution.xx;
    vec2 st = pixelize(uv);
    ivec2 texel = ivec2(st * iResolution.xx);

    // initialize the buffer with some noise on start
    if (iFrame == 0)
    {
        fragColor = vec4( step(0.9, fract(sin(dot(st + iDate.z, vec2(12.345, 97.34857))*33.2984)*456.2349) ) );
        return;
    }

    // paint at the mouse cursor
    if (pixelize(iMouse.xy/iResolution.xx) == st)
    {
        fragColor = vec4(1);
        return;
    }

    // only continue in iteration at every nth rendered frame
    if (iFrame % FRAME_INTERLACE != 0)
    {
        fragColor = texture(iChannel0, fragCoord/iResolution.xy);
        return;
    }


    // sum neighbooring alive cells
    int c = 0;
    for (int x = -1; x < 2; x++)
    for (int y = -1; y < 2; y++)
    {
        if (x == 0 && y == 0)
            continue;

        c += int(texelFetch(iChannel0, texel + ivec2(x,y), 0).r);
    }

    // center cell
    int x = int(texelFetch(iChannel0, texel, 0).r);

    vec3 live = vec3(0);

    if (x == 1 && c == 2 || c == 3)
        live = vec3(1);

    fragColor = vec4(live, 1.0);
}
