#version 450 core

// inputs 
in vec2 texCoord;

// outputs
out vec4 fragColor;

// uniforms
uniform sampler2D   t_texture0;
uniform float       g_time;
uniform float       g_glvel;
uniform vec3        g_gldots;
uniform float       g_glcolor;
uniform ivec2       g_resolution;

float rand(vec2 co){
    return 2.*(fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453)-.5);
}

float rand2(vec3 co){
    return 2.*(fract(sin(dot(co, vec3(12.9898, 28.233, 16.4495))) * 418.5453)-.5);
}

const float PI = 3.14159;

float sdBox( in vec2 p, in vec2 b )
{
    vec2 d = abs(p)-b;
    return length(max(d,0.0)) + min(max(d.x,d.y),0.0)-.02;
}

mat2 rotate(float a) {return mat2(cos(a), -sin(a), sin(a), cos(a));}

float urand(vec2 co) {return abs(rand(co));}

float t = g_time;
float it = (int((t + .4*sin(t*0.3) + .2*sin(t*0.9)) * 3.)) * .33;
float it2 = (int((t + .4*sin(t*0.3) + .2*sin(t*0.9)) * 7.)) * .08;
float it3 = (int((t + .5*sin(t*0.6) * .2*cos(t*1.6)) * 18.)) * (1./18.);

vec2 iuv = ivec2(texCoord*60);
vec2 iuv2 = ivec2(texCoord*vec2(30., 170.));

float it4 = (int((t + .2*sin(t*0.1) * .2*cos(t*2.4)) * 14.)) * (1./14.);

// render motion crap stuff =)
float dots(vec2 uv) {
	uv += vec2(0.5);
	if (rand(vec2(it3)) < -0.3) return 0.0;

	float gridsize = 2.0;

	uv *= vec2(float(g_resolution.x)/g_resolution.y, 1.);
    uv *= 40.;
    vec2 p = mod(uv, vec2(gridsize))-gridsize/2.;
    vec2 ip = uv - p;
	vec4 bbox = 30*(vec4(
		rand2(vec3(ip,3.5*(it2))), rand2(vec3(ip.yx,3.2*(it2))),
		rand2(vec3(ip,4.5*(it2))), rand2(vec3(ip.yx,1.3*(it2)))
		) + vec4(1.0));
    
	if ((ip.x < bbox.x) || (ip.y < bbox.y) || (ip.x > (bbox.x+bbox.z))|| (ip.y > (bbox.y+bbox.w))) return 0.0;
	
    p *= rotate(PI*float(int(rand2(vec3(ip.xy,it))) * 4.0)/4.0);
    
    int gridType = int(abs(g_gldots.y*rand(vec2(ip.xy + vec2(it)))) + g_gldots.z);
    
    float d = 90.0;
    // draw the square
    switch (gridType) {
    case 1:
        d = min(d,sdBox(p, vec2(0.06)));
        break;
    case 2:
        d = min(d,sdBox(p + vec2(0.03, 0.2), vec2(0.3, 0.07)));
        d = min(d,sdBox(p - vec2(0.2, 0.03), vec2(0.07, 0.3)));
        d = min(d,sdBox((p - vec2(-0.1, 0.1))*rotate(radians(45.)), vec2(0.3, 0.07)));
        break;
    case 3:
        d = min(d,sdBox(p, vec2(0.3, 0.02)));
        d = min(d,sdBox(p, vec2(0.02, 0.3)));
        break;
    case 4:
        d = min(d,sdBox(p, vec2(0.5)));
        p *= rotate(radians(45.));
        p.x = mod(p.x, .36)-.18;
        d = max(d,-sdBox(p, vec2(0.1, 0.9)));
        break;
    case 5:
        d = length(p)-.6;
        d = max(d, -(length(p)-.5));
        break;
    default:
        break;
    }
    
    // occlusion crap
    return 1.0 - sign(d)*smoothstep(0.0,0.04,abs(d));
}


#define BLUR_SAMPLES 16
void main(void) {
    vec2 uv = texCoord-.5;
  	float radius = dot(uv,uv);
  	
  	float glx = g_glvel*sin(it3*7.2)*rand(vec2(sin(it2*0.6+iuv*2.3)))*mod(float(iuv.x+.0001), 0.4);
 	float gly = g_glvel*cos(it3*7.2)*rand(vec2(sin(it2*0.1+iuv*2.3)))*mod(float(iuv.y+.0001), 0.4);
 	uv.x += glx;
	uv.y += gly;
	
    iuv = ivec2(uv*60);
    iuv2 = ivec2(uv*vec2(30., 170.));

	vec3 glc = mix(vec3(1.0), vec3(
 		rand(vec2(it3*7.2, iuv.y*2)),
 		rand(vec2(it2*7.2, iuv.x)),
 		rand(vec2(it3*7.2, rand(vec2(iuv.y*4,iuv.x))))
 	), clamp(g_glcolor*urand(iuv2*4), 0, 1));
 	uv.x += glx;
	uv.y += gly;
	
    fragColor = vec4(textureLod(t_texture0, uv+.5, 0.).rgb * (0.7*glc+0.3) + g_gldots.x*dots(uv), 1.0);
}


