#version 330 core

// inputz
in vec2 UV;
uniform vec2 iResolution;
uniform sampler2D iChannel1;
uniform sampler2D overlay;
uniform float overlayVisibility;
uniform float time;
// linear white point
uniform float W = 10.0;
uniform float T2 = 0.75;

// outputs
out vec4 color;

float hash(float c){return fract(sin(dot(c,12.9898))*43758.5453);}
float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec3 mod289(vec3 x) {
	return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec2 mod289(vec2 x) {
	return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec3 permute(vec3 x) {
	return mod289(((x*34.0)+1.0)*x);
}

float snoise(vec2 v) {
	const vec4 C = vec4( 0.211324865405187,  // (3.0-sqrt(3.0))/6.0
						 0.366025403784439,  // 0.5*(sqrt(3.0)-1.0)
						-0.577350269189626,  // -1.0 + 2.0 * C.x
						 0.024390243902439); // 1.0 / 41.0
	vec2 i  = floor(v + dot(v, C.yy) );
	vec2 x0 = v -   i + dot(i, C.xx);
	vec2 i1;
	i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
	vec4 x12 = x0.xyxy + C.xxzz;
	x12.xy -= i1;
	i = mod289(i);
	vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 ));
	vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
	m = m*m ;
	m = m*m ;
	vec3 x = 2.0 * fract(p * C.www) - 1.0;
	vec3 h = abs(x) - 0.5;
	vec3 ox = floor(x + 0.5);
	vec3 a0 = x - ox;
	m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
	vec3 g;
	g.x  = a0.x  * x0.x  + h.x  * x0.y;
	g.yz = a0.yz * x12.xz + h.yz * x12.yw;
	return 130.0 * dot(m, g);
} 
/*
float rand(vec2 co) {
	return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

float hash(float f) {
	return fract(sin(f * 11.1753) * 192652.37862);
}
*/
float noise(vec3 x) {
		vec3 p = floor(x);
		vec3 f = fract(x);
		f       = f*f*(3.0-2.0*f);
		float n = p.x + p.y*57.0 + 113.0*p.z;
		return mix(mix(mix( hash(n+0.0),   hash(n+1.0),  f.x),
									 mix( hash(n+57.0),  hash(n+58.0), f.x),f.y),
							 mix(mix( hash(n+113.0), hash(n+114.0),f.x),
									 mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

// for the lulz
float letterbox() {
	float w = iResolution.x / iResolution.y;
	float h = 1.0;

	float y = w / 2.39;
	float b = (h - y) / 2.0;

	return 1.0 - float((UV.y < b) || (UV.y > 1.0 - b));
}



float filmic_reinhard_curve (float x) {
    float q = (T2*T2 + 1.0)*x*x;    
  return q / (q + x + T2*T2);
}

vec3 filmic_reinhard(vec3 x) {
    float w = filmic_reinhard_curve(W);
    return vec3(
        filmic_reinhard_curve(x.r),
        filmic_reinhard_curve(x.g),
        filmic_reinhard_curve(x.b)) / w;
}

const int N = 14;

vec2 co(vec2 uv){
  return 0.5-uv*0.49;
}

vec3 ca(sampler2D t, vec2 UV, vec4 sample){
  vec2 uv = 1.0 - 2.0 * UV;
  vec3 c = vec3(0);
  float rf = 1.0;
  float gf = 1.0;
  float f = 1.0/float(N);
  for(int i = 0; i < N; ++i){
    c.x += f*texture(t, co(uv*rf) ).r;
    c.y += f*texture(t, co(uv) ).g;
    c.z += f*texture(t, co(uv*gf) ).b;
    rf *= 0.9996;
    gf *= 1.0005;
    c = clamp(c, 0.0, 1.0);
  }
  //return mix(c, sample.rgb, 1.0);
  return c;
}

void main()
{
    vec2 pp = UV;
    vec2 r = iResolution.xy;
    vec2 p = 1.-2.*UV;
    p.y *= r.y/r.x;
   
    // a little chromatic aberration
    vec4 sample = texture(iChannel1, pp);
    //vec3 c = sample.rgb;
    vec3 c = ca(iChannel1, pp, sample).rgb;
    //vec3 color = sample.rgb;
    
    // final output
    
    float vignette = 1.25 / (1.1 + 1.1*dot(p, p));
    float noise = .02*vec3(hash(length(p)*time)).x;
    vec4 texval = texture(overlay, vec2(UV.x, 1.0 - UV.y));
    c = pow(c, vec3(1.0/2.2));
    c = filmic_reinhard(c);
    color = vec4(vignette*c+noise, 1.0 );
    color.rgb *= letterbox();
    color += overlayVisibility * texval * texval.a;
}
