#version 330 core

// inputz
in vec2 UV;

uniform vec2 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;


// outputz
out vec4 fragColor;

mat3 orient(in vec3 v,in vec3 d)
{
    v = normalize(v);
    vec3 i = normalize(cross(v, normalize(d)));
    return mat3(i, cross(i, v), v);
}

vec3 previous(vec3 o, vec3 t, vec3 d)
{
    vec3 tv = vec3(1);
    float off = 3.0*(1.0*pow(length(tv),2.0) );
    float r = 32.0 - off;

    float a = d.x*d.x + d.y*d.y;
    float b = 2.0*(o.x*d.x + o.y*d.y);
    float c = o.x*o.x + o.y*o.y - r*r;

    float delta = b*b - 4.0*a*c;

    float t1 = (-b - sqrt(delta))/(2.0*a);
    float t2 = (-b + sqrt(delta))/(2.0*a);

    return o + min(t1, t2)*d;
}

void main()
{
    vec2 uv = -1.0+2.0*UV;
    uv.x *= iResolution.x/iResolution.y;
    
    float T = iTime*1.5;
    
    // origo and lookat points
    vec3 o = vec3(sin(T*0.478)*6.0,cos(T*0.513)*6.0, T*100.0);
    vec3 t = vec3(sin(T*0.509)*160.0,cos(T*0.437)*160.0, -1000.0);
    // oriented direction vectors (yes I like my up vectors like that shut your up)
    vec3 d = normalize(vec3(uv, 1.0)*orient(t, normalize(vec3(0,1,0)) ));
    
    vec3 tv = vec3(1);
    vec3 ac = vec3(0);
    vec3 i = vec3(0);
    vec3 i_o = i;
    float aid = 0.0;
    
    for(int l = 0; l < 32; l++)
    {
        float off = 4.5*(1.0*pow(length(tv),2.0) );
        aid += off;
        float r = 32.0 - off;
    
        float a = d.x*d.x + d.y*d.y;
        float b = 2.0*(o.x*d.x + o.y*d.y);
        float c = o.x*o.x + o.y*o.y - r*r;

        float delta = b*b - 4.0*a*c;

        float t1 = (-b - sqrt(delta))/(2.0*a);
        float t2 = (-b + sqrt(delta))/(2.0*a);
        float t = min(t1, t2);

        i = o + t*d;
        vec2 co = vec2((i.z)*0.2,
                       atan(i.y, i.x)*32.0/3.1416);
        tv = texture(iChannel0, co*0.007).rgb;
        vec2 c2 = vec2((i.z)*0.2,
                       abs(atan(i.y, i.x)*32.0/3.1416));
        vec3 te = texture(iChannel0, c2*0.007).rgb;
        tv = mix(tv, te, smoothstep(0.0,0.7,atan(i.y, i.x))+smoothstep(3.1416-0.7,3.1416,-atan(i.y, i.x)));
        
        ac += pow(tv, vec3(2.2))/32.0;
    }
    
    ac /= pow(smoothstep(0.0, 2.0, 1.0/pow(distance(o, i)*0.02, 2.0)), 0.5);
    ac /= pow(aid, 0.25)*0.25;
    
    fragColor.rgb = ac;
    
    // MOTION VECTOR STUFF
    /////////////////////////////////////////////////////////////
    // "previous" camera position
    const float TD = (-1.0/24.0)*1.5;
    vec3 o_p = vec3(sin(TD+T*0.478)*6.0,cos(TD+T*0.513)*6.0, TD+T*100.0);
    vec3 t_p = vec3(sin(TD+T*0.509)*160.0,cos(TD+T*0.437)*160.0, -1000.0);
    mat3 OC = orient(t_p, normalize(vec3(0,1,0)) );
    vec3 d_p = normalize(vec3(uv, 1.0)*OC);
    
    // from IQ
    vec3 vv = i;
    vec3 cpos = vec3(dot(vv - o_p, OC[0]),
                     dot(vv - o_p, OC[1]),
                     dot(vv - o_p, OC[2]));
    
    // ndc space
    vec2 npos = 0.75 * cpos.xy / (cpos.z);
    // screen space
    vec2 spos = 0.5 + 0.5*npos*vec2(iResolution.y/iResolution.x,1.0);
    
    uv = UV;
    spos = clamp( 0.5 + 0.5*(spos - uv)/0.25, 0.0, 1.0 );
    float vc = floor(spos.x*255.0) + floor(spos.y*255.0)*256.0;
    fragColor.a = vc;
}
