uniform float iGlobalTime;
uniform vec3 iResolution;
uniform vec2 iMouse;
//uniform samplerCube iChannel1;

uniform sampler2D iChannel0;
uniform sampler2D iChannel2;

uniform float u_sync;
uniform float u_vhs;

float rand(float x)
{
// return fract(sin(x) * 43758.5453);
//float ee = iGlobalTime;
	return texture2D(iChannel0, vec2(x*9.92343,x*1.1235123)).r;
}

void main(void)
{
	vec2 uv = gl_FragCoord.xy / iResolution.xy;

//	uv.y = 1.0 - uv.y;

	mat3 rgbtoyuv = mat3(0.299, -0.147,  0.615, 0.587, -0.289, -0.515, 0.114, 0.436, -0.100);
	mat3 yuvtorgb = mat3(1.000, 1.000, 1.000, 0.000, -0.395, 2.032, 1.140, -0.581, 0.000);


	vec2 uv_q = uv;
	uv_q.y = uv_q.y * (480.0 / 525.0);// + (480.0 / 525.0) * (525.0 - 480.0);

	//if (rand(iGlobalTime) > 0.3)

	float syncfuck = mod(u_sync * 3.9238472, 1.0);
	float syncfuck2 = syncfuck + 0.2;

	if (u_sync < -0.1)
	{
		if (uv_q.y > syncfuck2)
		{
			uv_q.y = syncfuck2 + uv_q.y - syncfuck;
			uv_q.x += syncfuck2 - syncfuck;
		}
		else if (uv_q.y > syncfuck)
		{
			uv_q.y = uv_q.y - syncfuck;
			uv_q.x += uv_q.y - syncfuck;
		}
	}

//	 did we just lost sync?
	uv_q.y += u_sync;


//	uv_q.y = floor(uv.y * 486.0) / 486.0;

	//float shade = 1.0 - pow(fract(uv.y * 486.0), 1.0) * 0.5;

	// global YUV noise
    float shade = 1.0;
    shade -= rand(uv_q.x * 0.1 + uv_q.y * 50.0 + iGlobalTime) * 0.5;

	vec2 uv_n = uv_q;

    if (u_vhs > 0.5)
    {
    	uv_n.y += rand(iGlobalTime * 12.) * 0.004;

	    // small scanline-based X-position noise = tape wrinkles
		uv_n.x += rand(uv_q.y*39.0+iGlobalTime * 20.0) * 0.004 - 0.002;

		// global sinus wobbling
		float xsin = sin(iGlobalTime * 10.0 + uv_q.y * 9.0);
		float fugran = rand(iGlobalTime * 235.0);
		uv_n.x += xsin * clamp(fugran - 0.98, 0.0, 1.0) * 0.5;

		float xsin3 = sin(iGlobalTime * 5.0 + uv_q.y * 12.0);
		float fugran3 = rand(iGlobalTime * 235.0);
		uv_n.x += xsin3 * clamp(fugran3 - 0.94, 0.0, 1.0) * 0.5;


		// y poition jumping
		float fugran2 = rand(iGlobalTime * 511.0);
		uv_n.y += clamp(fugran2 - 0.98, -0.1, 1.0) * 0.01;

		// x-position noise = little tape jitter 
		uv_n.x += rand(dot(uv_q,vec2(10.0,56.0)) + iGlobalTime * 21.0) * 0.003;
	}


	vec3 yuv = vec3(0.0);
	float fix = 0.3;
	float lumadelay = -0.002;

	// chroma bleed wobbling
    if (u_vhs > 0.5)
    {
		fix = 0.5;
		fix += sin(iGlobalTime * 2.3) * 0.2;
		fix += sin(iGlobalTime * 5.52) * 0.1;
		fix += sin(iGlobalTime * 23.0) * 0.1;
		fix += rand(uv_q.y*59.0+iGlobalTime * 30.0) * 0.4;
		fix *= 0.5;
		lumadelay = -0.005 + rand(uv_q.y*45.+iGlobalTime * 23.0) * 0.003;
	}

//	fix = 0.1;
//	lumadelay = -0.01;


	// blur
	for (float x = 1.0; x >= 0.0; x -= 0.1)
	{
		float x1 = (x * -0.05)* fix + lumadelay;
		float x2 = (x * 0.1)* fix + lumadelay;

		vec3 mult = (vec3(1.0) - pow(vec3(x), vec3(0.2, 1.0, 1.0))) * 0.2;
		vec2 uv1 = uv_n + vec2(x1,0.0);
		vec2 uv2 = uv_n + vec2(x2,0.0);
		vec2 uv1b = uv_n + vec2(x1, 1.0/486.0);
		vec2 uv2b = uv_n + vec2(x2, 1.0/486.0);

		yuv += (rgbtoyuv * texture2D(iChannel2, uv1).rgb) * mult;
		yuv += (rgbtoyuv * texture2D(iChannel2, uv2).rgb) * mult;
//		yuv.gb += (rgbtoyuv * texture2D(iChannel2, uv1b).rgb).gb * mult.gb;
//		yuv.gb += (rgbtoyuv * texture2D(iChannel2, uv2b).rgb).gb * mult.gb;
	}

	// normalize Y a bit
	yuv.r = yuv.r * 0.2 + (rgbtoyuv * texture2D(iChannel2, uv_n).rgb).r * 0.8;


	if (u_vhs > 0.5)
	{
		// turn to grayscale when tape is really bad
		float runran = rand(iGlobalTime * 666.0);
		if (runran > 0.91)
			yuv.gb = vec2(0.0);

		float noiseamount = 0.0;
		float noiseenable = max(0.0, rand(iGlobalTime * 440.0 + uv.y * 440.0) - 0.995) / 0.015;
		if (noiseenable > 0.5)
				yuv.gb = vec2(0.0);
//		noiseamount = (0.5 + sin( (floor(uv.y * 480.) + uv.x) * 0.0001) * 0.5) * noiseenable;
		noiseamount = (0.5 + sin(uv.x * 3.0 + iGlobalTime * 10.0) * 0.5) * noiseenable;
		yuv.r = mix(yuv.r, rand(iGlobalTime * 11. + uv_n.x * 13. + uv_n.y * 12.), noiseamount);
//		yuv.r = noiseamount;
	}


	// something
//	float runran2 = (clamp(rand(uv_q.x * 30.3 + iGlobalTime * 566.0 + uv_q.y * 0.1), 0.99, 1.0)-0.96) / 0.01;
//	yuv = mix(yuv, vec3(rand(uv_q.x * 0.132 + uv_q.y * 25.0 + iGlobalTime * 3.0), 0.0, 0.0), runran2);

//	yuv.gb *= vec2((iMouse.y / iResolution.y)*10.0);
    //yuv.r += ((iMouse.x / iResolution.x)-0.5);
	//yuv.r = 1.0;
	//yuv.g = -0.0;
	//yuv.b = -0.0;
    
//    yuv.r *= 3.0;

//   yuv.gb *= 0.7;

	// add noise individually to all YUV components
    
//
/*
    yuv.r += (rand(uv_q.x * 0.032 + uv_q.y * 35.0 + iGlobalTime * 3.0) - 0.5) * 0.2;
    yuv.g += (rand(uv_q.x * 0.042 + uv_q.y * 38.0 + iGlobalTime * 4.0) - 0.5) * 0.3;
    yuv.b += (rand(uv_q.x * 0.022 + uv_q.y * 34.0 + iGlobalTime * 5.0) - 0.5) * 0.3;
*/


/*
	float thispix = length(texture2D(iChannel2, uv_n).rgb);
	float thispix2 = length(texture2D(iChannel2, uv_n-vec2(0.0,1.0/640.)).rgb);

	float lumableed = 1.0 + abs(thispix2 - thispix) * 10.0;

    yuv.r += (rand(uv_q.x * 0.32 + uv_q.y * 9.5 + iGlobalTime * 9.5) - 0.5) * 0.2;
    yuv.g += (rand(uv_q.x * 0.42 + uv_q.y * 8.6 + iGlobalTime * 8.6) - 0.5) * 0.3 * lumableed;
    yuv.b += (rand(uv_q.x * 0.22 + uv_q.y * 7.4 + iGlobalTime * 7.4) - 0.5) * 0.3 * lumableed;
*/
//	yuv.r = pow(yuv.r, 2.0);
//	yuv.gb *= 0.6;
//	gl_FragColor.rgb = pow((yuvtorgb * yuv * shade) * vec3(2.0), vec3(1.2));
	gl_FragColor.rgb = yuvtorgb * yuv * shade;
//    gl_FragColor = texture2D(iChannel2, uv);

}
