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

const int NUM_SAMPLES = 8;
const float OFFSET = 0.05;
const float ZOOM_MULTIPLIER = 2.;

vec3 srgb2lin(vec3 c)
{
	return pow(c, vec3(2.2));
}

vec3 lin2srgb(vec3 c)
{
	return pow(c, vec3(1.0 / 2.2));
}

vec3 drawBlur(vec2 fragCoord, vec2 blurDir1, vec2 blurDir2)
{
	float blurDist = NUM_SAMPLES * 4.0 * (0.55 + 0.45 * sin(5.0 * fragCoord.x + pts));

	vec2 blurVec1 = normalize(blurDir1) / texSize.xy;
	vec2 start1  = fragCoord - intensity * blurDist * blurVec1;
	vec2 end1    = fragCoord + intensity * blurDist * blurVec1;
	vec2 stepVec1 = (end1 - start1) / float(NUM_SAMPLES);

	vec2 blurVec2 = normalize(blurDir2) / texSize.xy;
	vec2 start2  = fragCoord - intensity * blurDist * blurVec2;
	vec2 end2    = fragCoord + intensity * blurDist * blurVec2;
	vec2 stepVec2 = (end2 - start2) / float(NUM_SAMPLES);
	vec2 p = start2 + stepVec2;

	vec3 res = vec3(0.);
	for (int i = -(NUM_SAMPLES / 2); i < NUM_SAMPLES / 2; ++i)
	{
		for (int j = 0; j < NUM_SAMPLES; ++j)
		{
			res += srgb2lin(texture2D(tex, p).rgb);
			p += stepVec2;
		}
		p = start2 + stepVec2 + i * stepVec1;
	}
	res /= float(NUM_SAMPLES * NUM_SAMPLES);

	return lin2srgb(res);
}

void main()
{
	vec2 fragCoord = TexCoord0 + vec2(sin(pts), cos(pts)) * OFFSET * intensity;
	fragCoord = (fragCoord - 0.5) * (1. - ZOOM_MULTIPLIER * OFFSET * intensity) + 0.5;
	vec3 res1 = srgb2lin(drawBlur(fragCoord, vec2(1.0, 0.0), vec2(0.0,  1.0)));
	vec3 res2 = srgb2lin(drawBlur(fragCoord, vec2(1.0, 1.0), vec2(1.0, -1.0)));
	gl_FragColor = vec4(lin2srgb(min(res1, res2)), texture2D(tex, fragCoord).a);
}
