#version 330 core

out vec4 FragColor;

uniform vec3 iResolution;
uniform float iTime;
uniform float uAlpha;
uniform sampler2D iChannel0;
uniform vec4 iMouse;

#define PI 3.14159

// ----- complex functions -----

// complex exponential
vec2 cexp(vec2 c) {
    return exp(c.x) * vec2(cos(c.y), sin(c.y));
}
// complex logarithm
vec2 cln(vec2 c) {
    return vec2(log(dot(c, c)) * .5, atan(c.y, c.x));
}
// complex multiplication
vec2 cmul(vec2 a, vec2 b) {
    return vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
// complex conjugation
vec2 conj(vec2 c) { return vec2(c.x, -c.y); }
// complex division
vec2 cdiv(vec2 a, vec2 b) {
    return cmul(a, conj(b)) / dot(b, b);
}

// ----- image -----
vec4 image(vec2 p, float scale) {
    vec2 a = abs(p);
    float i = floor(log2(max(a.x, a.y)) / log2(scale));
    // [-1, 1] coords
    p *= pow(scale, -i);
    a = abs(p);
    return mix(textureLod(iChannel0, p / scale * .49 + .5, 0.), textureLod(iChannel0, p * .49 + .5, 0.), min(1., (max(a.x, a.y) - scale) / scale / 0.01));
}

void mainImage(out vec4 fragColor, in vec2 z) {
    float scale = 1. / (2.2 + sin(iTime));
    scale *= scale;
    z = (z - iResolution.xy * .5) / iResolution.y * 10.;
    
    // Droste transform here
    vec2 mouse = (length(iMouse.xy) > 0.0001) ? (iMouse.xy / iResolution.xy + vec2(0.2, 0.1)) : vec2(0.2, 0.1);
    z = cdiv(z, cmul(mouse, mouse));
    float ln_scale = log(scale);
    z = cmul(cln(z), vec2(2. * PI, -ln_scale) / (2. * PI));
    //z.y -= mod(iTime*2., 2.*PI);
    z.x -= mod(iTime * 6., 2. * PI) / (2. * PI) * ln_scale;
    z = cexp(z); // here with this it's just a periodic grid
    // Drawing time.
    fragColor = image(z, scale);
    fragColor.a *= uAlpha;
}

void main()
{
    vec4 color = vec4(0.0);
    mainImage(color, gl_FragCoord.xy);
    FragColor = color;
}
