varying vec2 TexCoord0;
uniform sampler2D tex;
uniform sampler2D auxTex;
uniform vec2 texSize;
uniform vec2 auxTexSize;
uniform float pts;
uniform float intensity;

const int ANGLE_NUM = 3;
const int SAMPLE_NUM = 16;
const float GLOBAL_SCALE = 400.;

//const vec3 CHROMAKEY_EXTRACT_COLOR = vec3(1.0, -0.5, -0.5); // Red
const vec3 CHROMAKEY_EXTRACT_COLOR = vec3(-0.5, 1.0, -0.5); // Green
//const vec3 CHROMAKEY_EXTRACT_COLOR = vec3(-0.5, -0.5, 1.0); // Blue

const float PI2 = 6.28318530717959;

#define USE_CHROMAKEY

vec3 getRand(vec2 pos)
{
    return texture2D(auxTex, fract(pos / auxTexSize)).rgb;
}

/// Process chroma key
vec3 getCol(vec2 pos)
{
	vec2 uv = pos / texSize;
	vec3 origColor = texture2D(tex, uv).rgb;
#ifdef USE_CHROMAKEY
	float chromaExtractFactor = clamp(dot(origColor, CHROMAKEY_EXTRACT_COLOR), 0.0, 1.0);
	vec3 chromaExtractBrightness = vec3(0.7 * intensity / .5);
	return min(mix(origColor, chromaExtractBrightness, 1.8 * chromaExtractFactor), .7);
#else
	return origColor;
#endif
}

/// Add some 'paper' noise
vec3 getColHT(vec2 pos)
{
	return smoothstep(.95, 1.05, getCol(pos) * .8 + .2 + getRand(pos * .7));
}

float getVal(vec2 pos)
{
	vec3 c = getCol(pos);
	return dot(c, vec3(.333));
}

vec2 calcGrad(vec2 pos, float eps)
{
	vec2 d = vec2(eps, 0);
	return vec2(
			getVal(pos + d.xy) - getVal(pos - d.xy),
			getVal(pos + d.yx) - getVal(pos - d.yx)
		) / eps / 2.;
}

void main()
{
	vec2 fragCoord = TexCoord0 * texSize; // use unnormalized coordinates
	vec2 pos = fragCoord + 4.0 * sin(pts * vec2(1, 1.7)) * texSize.y / GLOBAL_SCALE; // add some moving to coordinates
	float blur = 0.;
	vec3 color = vec3(0);
	float sum = 0.;
	for(int i = 0; i < ANGLE_NUM; ++i)
	{
		float angle = PI2 / float(ANGLE_NUM) * (float(i) + .8);
		vec2 rot = vec2(cos(angle), sin(angle));
		for(int j = 0; j < SAMPLE_NUM; ++j)
		{
			vec2 dpos  = rot.yx * vec2(1, -1) * float(j) * texSize.y / GLOBAL_SCALE;
			vec2 dpos2 = rot.xy * float(j * j) / float(SAMPLE_NUM) * .5 * texSize.y / GLOBAL_SCALE;

			for(float s = -1.; s <= 1.; s += 2.) // two passes
			{
				vec2 pos2 = pos + s * dpos + dpos2;
				vec2 pos3 = pos + (s * dpos + dpos2).yx * vec2(1, -1) * 2.;
				vec2 grad = calcGrad(pos2, .4);
				float fact = dot(grad, rot) - .5 * abs(dot(grad, rot.yx * vec2(1, -1)));
				float fact2 = dot(normalize(grad + vec2(.0001)), rot.yx * vec2(1, -1));

				fact = clamp(fact, 0., .05);
				fact2 = abs(fact2);

				fact *= 1. - float(j) / float(SAMPLE_NUM);
				blur += fact;
				color += fact2 * getColHT(pos3);
				sum += fact2;
			}
		}
	}

	color /= sum;

	blur /= float(SAMPLE_NUM * ANGLE_NUM) * .75 / sqrt(texSize.y);
	blur *= (.6 + .8 * getRand(pos * .7).r);
	blur = 1. - blur;
	blur *= blur * blur;

	vec2 s = sin(pos * .1 / sqrt(texSize.y / GLOBAL_SCALE));
	vec3 checks = vec3(1) - .5 * vec3(.25, .1, .1) * dot(exp(-s * s * 80.), vec2(1));
	gl_FragColor = vec4(vec3(blur * color * checks), texture2D(tex, TexCoord0).a);
}
