uniform float iTime;

vec3 coloring(vec3 a, vec3 b, vec3 c, vec3 d, float t)
{
    return a + b * cos(6.28 * (c * t + d));
}

vec2 random( vec2 p ) {
    return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}

float manhattan(vec2 a, vec2 b)
{
    return (abs(a.x - b.x) + abs(a.y - b.y));
}

vec2 voronoi(vec2 uv)
{
    uv.x *= 24.;
    uv.y *= 16.;
    
    vec2 tile = floor(uv);
    vec2 pixel = fract(uv);
    
    vec2 minDist = vec2(50.);
    vec2 minId = vec2(0.);
    
    for (int y = -1; y <= 1; y++)
    {
        for (int x = -1; x <= 1; x++)
        {
            vec2 n = vec2(x, y);
            vec2 p = random(tile + n);
            
            p = sin(iTime * p) / 2. + 0.5;
            
            vec2 q = p + n - pixel;
            float dist = dot(q,q);
            //float dist = manhattan(pixel, p + n);
                        
            if (dist < minDist.x)
            {
                minDist.y = minDist.x;
                minDist.x = dist;
                minId = vec2(tile + n);
            }
            else if (dist < minDist.y)
            {
                minDist.y = dist;
                minId = vec2(tile + n);
            }
            
        }
    }
    
    return minId;
}

vec2 manhattanoi(vec2 uv)
{
    uv.x *= 24.;
    uv.y *= 16.;
    
    vec2 tile = floor(uv);
    vec2 pixel = fract(uv);
    
    vec2 minDist = vec2(50.);
    // vec2 minDist = vec2(1000.);
    vec2 minId = vec2(0.);
    
    for (int y = -1; y <= 1; y++)
    {
        for (int x = -1; x <= 1; x++)
        {
            vec2 n = vec2(x, y);
            vec2 p = random(tile + n);
            
            p = sin(iTime * p) / 2. + 0.5;
            
            //vec2 q = p + n - pixel;
            //float dist = dot(q,q);
            float dist = manhattan(pixel, p + n);
                        
            if (dist < minDist.x)
            {
                minDist.y = minDist.x;
                minDist.x = dist;
                minId = vec2(tile + n);
            }
            else if (dist < minDist.y)
            {
                minDist.y = dist;
                minId = vec2(tile + n);
            }
            
        }
    }
    
    return minId;
}

float getBorder(vec2 p)
{
    float a = p.y - p.x;
    
    return 1. - smoothstep(0., 0.05, a);
}

void main()
{
    // Normalized pixel coordinates (from 0 to 1)


    // oskar
    //vec2 uv = fragCoord/iResolution.xy;

    // albin
    vec2 uv = gl_TexCoord[0].xy;
    
    //float v = voronoi(uv);
    vec2 v = voronoi(uv);
    vec2 m = manhattanoi(uv);
    //float border = getBorder(v);
    
    //vec2 voronoiUv = uv * vec2(12., 8.);
    //vec2 slask = v / voronoiUv;
    //vec2 slask = smoothstep(vec2(1.), vec2(0.5), v);//step(0.5, 1. - v);
    
    //vec3 tex = texture(iChannel0, uv + slask).xyz;
    
    vec3 colA = vec3(coloring(vec3(0.5), vec3(0.5), vec3(1.), vec3(0., 0.33, 0.667), length(v + 7.)));
    vec3 colB = vec3(coloring(vec3(0.5), vec3(0.5), vec3(1.), vec3(0., 0.33, 0.667), length(m + 7.)));
    
    float t = smoothstep(0.3, 0.7, sin(iTime) / 2. + 0.5);
    
    vec3 col = mix(colA, colB, t);//sin(iTime) / 2. + 0.5);
    //col.xy = vec2(v3.y, v3.z);

    // Output to screen
    gl_FragColor = vec4(col,1.0);
}