#version 450 core

// inputs 
in vec2 texCoord;

// outputs
out vec4 fragColor;

// uniforms
uniform sampler2D   t_texture0;
uniform sampler2D   t_texture0_nearest;
uniform sampler2D   t_bluenoise;
uniform ivec3       g_resolution;
uniform float		g_time;
uniform float		g_glrand;
uniform float 		g_glgamma;
uniform float	    g_glfreq;	// frequency of glitches change in hz
uniform int			g_overlay;	// 0 - none, 1 - ZX, 2 - BK

// Gold Noise ©2015 dcerisano@standard3d.com
// - based on the Golden Ratio
// - uniform normalized distribution
// - fastest static noise generator function (also runs at low precision)
// - use with indicated seeding method. 

float PHI = 1.61803398874989484820459;  // Φ = Golden Ratio   

float gold_noise(in vec2 xy, in float seed){
       return fract(tan(distance(xy*PHI, xy)*seed)*xy.x);
}

const vec2 uniformRes = vec2(640., 320);
ivec2 uvUniformNearest = ivec2(texCoord * uniformRes);
vec2  uvUniform = vec2(uvUniformNearest/uniformRes);
vec2 uv_bn = ivec2(
    mod(uvUniformNearest, ivec2(textureSize(t_bluenoise, 0))))/vec2(textureSize(t_bluenoise, 0));

float RGBtoY(vec3 a) {
    return dot(a, vec3(.2126, .7152, .0722));
}

vec3 calcBase(vec3 a) {
	float bright = step(0.5,RGBtoY(pow(a, vec3(g_glgamma))));
	vec3 rgb = (0.2+0.8*bright)*clamp(step(0.5*(0.2*bright+0.4),a), 0, 1);
	
	return vec3(rgb);
}

vec3 doZXMulticolor(vec3 incol) {
	vec3 a = pow(textureLod(t_texture0_nearest,
	    texCoord, 3.+log2(g_resolution.x/uniformRes.x)).rgb, vec3(g_glgamma)*vec3(0.6,1.2,0.54));
	return clamp(vec3(ivec3(a * 4.)/5.), 0., 1.);
}

vec3 doZX(vec3 incol) {
	vec3 baseColor = calcBase(pow(textureLod(t_texture0_nearest,
	    texCoord, 3.+log2(g_resolution.x/uniformRes.x)).rgb, vec3(g_glgamma)));
	
	ivec3 thresh = ivec3(greaterThan(incol, 0.4*baseColor));
	vec3 outcol = baseColor*vec3(step(3,float(thresh.r + thresh.g + thresh.b)));
	return outcol;
}

vec3 doBK(vec3 incol) {
    // override incol
	incol = clamp(textureLod(t_texture0_nearest, uvUniform, 0).rgb + 
         0.5*(textureLod(t_bluenoise, uv_bn, 0).rgb),
         0., 1.);
    incol = pow(incol, vec3(g_glgamma));
	bvec3 thresh = greaterThan(incol, vec3(0.4));
    vec3 outcol = (incol.r > incol.b ?
            (incol.r > incol.g ? vec3(thresh.r,0,0) : vec3(0,thresh.g,0)) :
            (incol.b > incol.g ? vec3(0,0,thresh.b) : vec3(0,thresh.g,0)));
    return outcol;
}

float t = g_time;
float it = (int((t + .2*sin(t*2.7)*cos(t*2.4)*.2*sin(t*0.9)) * g_glfreq)) * (1./g_glfreq);

void main(void) {
	vec2 iuv = ivec2(texCoord * textureSize(t_texture0_nearest,
	           int(5.+log2(float(g_resolution.x)/uniformRes.x))) * vec2(2, 1));
	
    vec3 col = textureLod(t_texture0_nearest, texCoord, 0.).rgb;
    vec3 incol = 
        clamp(textureLod(t_texture0_nearest, uvUniform, 0).rgb + 
         0.5*(textureLod(t_bluenoise, uv_bn, 0).rgb-0.5),
         0., 1.);
   
    incol = pow(incol, vec3(g_glgamma));
    vec3 outcol = vec3(0.);
    
    switch (g_overlay) {
    	case 1:
    		outcol = doBK(incol);
    		break;
    	
    	case 2:
    		outcol = doZX(incol);    	
    		break;
    		
    	case 3:
    		outcol = doZXMulticolor(incol);    	
    		break;
    		
    	default:
    		{
    		    float f = gold_noise(iuv+vec2(9.4,3.5)+it, it);
    		    if (f > g_glrand) {
    		    	int a = int(((f - g_glrand) / (1.001 - g_glrand))*1.5);
					outcol = mix(col, (a < 1 ? (a < 2 ? doZX(incol) : doBK(incol)) : doZXMulticolor(incol)), 0.8);
    		    } else
    				outcol = col;;
    		}
    		break;
    }


    fragColor = vec4(outcol, 1.0);
    //fragColor = vec4(textureLod(t_texture0_nearest, texCoord, 0.).rgb, 1.0);
}



















