#define SCALE 6.0
#define R iResolution.xy
#define M iMouse
#define PI 3.14159265358979
#define PI2 6.2831853071795865
#define KT(i) texelFetch(iChannel1, ivec2(i, 2), 0).x > 0.0

void mainImage( out vec4 RGBA, in vec2 XY )
{
    float t = iTime;
    float nt = 8.0; // number of transforms
    float ts = 10.0; // time between transforms
    float ct = 20.0; // cell time
    vec2 m = M.xy/R; // mouse coords
    if (M.z > 0.0) t = m.x*nt*ts; // time from mouse x
    float z = (M.z > 0.0) ? 1.0/(1.0-m.y): 1.0; // zoom from mouse y
    vec2 uv = (XY-0.5*R)/R.y*SCALE*z; // screen coords
    
    vec2 uv2 = uv;
    float x = uv.x;
    float y = uv.y;
    float r = length(uv); // screen radius
    float a = atan(uv.x, uv.y); // screen arc
    float mode = mod(floor(t/ts), nt)+1.0; // mode from time
    float tt = (cos(PI+t*PI2/ts)+1.0)/2.0; // transform with time
    
    if (mode == 1.0) // polar
    {
        uv2 = vec2( a/PI2, r*5.0 );
    }
    else if (mode == 2.0) // metallic series
    {
        uv2 = ((x*x+y*y)-1.0)/uv;
    }
    else if (mode == 3.0) // power series
    {
        vec2 v = vec2( log(abs(x)), log(abs(y)) );
        uv2 = vec2( v.y/v.x, v.x/v.y );
    }
    else if (mode == 4.0) // waves
    {
        uv2 = y-vec2( cos(x), sin(x) );
    }
    else if (mode == 5.0) // circles & squares
    {
        vec2 v = vec2( sin(uv*PI) );
        uv2 = vec2( v.x+v.y, v.x-v.y );
    }
    else if (mode == 6.0) // archimedean spirals
    {
        float v = a/PI2;
        uv2 = r+vec2( v*3.0, -v*12.0 );
    }
    else if (mode == 7.0) // inverse square
    {
        vec2 v = uv/dot(uv, uv); // = uv/(x*x+y*y); // uv*pow(length(uv), -2.0);
        uv2 = v*3.0;
    }
    else if (mode == 8.0) // mobius (needs work)
    {
        vec2 u = uv-vec2(1.0, 0);
        vec2 v = u/dot(u, u);
        v.x += 0.5;
        uv2 = log(length(v)) * vec2(1.445, -1.445) + atan(v.y, v.x)/PI2 * vec2(4.0, 12.0);
    }
    
    uv = uv*(1.0-tt)+uv2*tt; // transform x & y
    
    vec3 c = vec3(0); // background
    
    if (KT(84)) // T key toggle
    {
        c += texture(iChannel0, uv, 1.0).rgb;
        vec2 dl = max(vec2(0.25), abs(sin(uv*PI))); // dark lines
        c *= min(dl.x, dl.y);
    }
    
    vec2 fw = fwidth(uv); // pixel size
    vec2 g = abs(fract(uv+0.5)-0.5)/fw; // grid
    c += max(0.0, 1.0-min(g.x, g.y))*0.3; // lines
    c += max(0.0, 1.0-max(g.x, g.y)/2.0)*0.6; // points
    
    vec2 c1 = (fract(uv-vec2(t/ct*round(uv.y), 0)+0.5)-0.5)/fw/3.0; // x cells
    vec2 c2 = (fract(uv-vec2(0, t/ct*round(uv.x))+0.5)-0.5)/fw/3.0; // y cells
    c.r += max(0.0, 1.0-length(c1)); // red dots
    c.b += max(0.0, 1.0-length(c2)); // blue dots
    
    RGBA = vec4(c, 1.0);
}
