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

const float PI2 = 6.283185307179586476925286766559;
const float SQRT_3 = 1.732050807568877293527446341506;
const float REF_SIZE = 1920.0;
const float ZOOM = 0.95; // For avoiding hexagon shifting over the texture border.

float getRand(vec2 coord);

vec2 cubeToAxial(vec3 cube)
{
	return cube.xz;
}

vec3 axialToCube(vec2 hex)
{
	return vec3(hex.x, -hex.x - hex.y, hex.y);
}

vec3 roundCube(vec3 cube)
{
	vec3 r = floor(cube + 0.5);
	vec3 diff = abs(r - cube);

	if (diff.x > diff.y && diff.x > diff.z)
		r.x = -(r.y + r.z);
	else if (diff.y > diff.z)
		r.y = -(r.x + r.z);
	else
		r.z = -(r.x + r.y);

	return r;
}

vec2 roundAxial(vec2 hex)
{
	return cubeToAxial(roundCube(axialToCube(hex)));
}

vec2 getHexCoord(vec2 point)
{
	float q = dot(vec2(SQRT_3, -1.0), point / 3.0);
	float r = 2.0 / 3.0 * point.y;
	return roundAxial(vec2(q, r));
}

vec2 getHexOffset(vec2 hexCoord)
{
	float azimuth = getRand(hexCoord) * PI2;
	return vec2(cos(azimuth), sin(azimuth));
}

float getRefractionFactor(vec2 uv)
{
	float dist = 2.0 * distance(uv, vec2(0.5));
	dist = clamp(dist, 0.0, 1.0);
	return pow(dist, 1.5);
}

void main()
{
	float hexSize = 15.0 + 30.0 * intensity;

	// Getting rid of dependence on size of input image,
	// the number of hexаgons at any size should be the same as at fullHD size
	hexSize *= max(texSize.x, texSize.y) / REF_SIZE;

	float hexHeight = SQRT_3 * hexSize;
	float hexWidth = 2.0 * hexSize;

	vec2 hexPos = TexCoord0 * texSize / vec2(hexWidth, hexHeight);
	vec2 hexCoord = getHexCoord(hexPos);

	float shiftR = getRand(vec2(hexCoord.x));
	float shiftG = getRand(vec2(hexCoord.y));
	float shiftB = getRand(vec2(hexCoord.x, hexCoord.y));
	float shiftI = getRand(vec2(hexCoord.y, hexCoord.x));

	vec2 hexOffset = getHexOffset(hexCoord);

	float factor = getRefractionFactor(TexCoord0);
	vec2 shiftedTexCoord = TexCoord0 + hexOffset * factor * 0.02;
	shiftedTexCoord = (shiftedTexCoord - 0.5) * ZOOM + 0.5; // Zoom from center
	vec4 color = texture2D(tex, shiftedTexCoord);
	color.rgb -= vec3(shiftR,shiftG,shiftB) * shiftI * factor * 0.05; // Tone shift per hexаgon
	gl_FragColor = color;
}

float getRand(vec2 coord)
{
	return movavi_rand_(mat2(1.0), vec2(1.0), coord);
}
