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

const float PATTERN_ZOOM = 3.0;
const float MAX_SHIFT = 0.03333;
const float ZOOM = 1.0 - MAX_SHIFT;

const float PI2 = 6.28318530717959;

float getRand(vec2 coord);

// Returns separated region id and distance to neares region border.
vec2 getPattern(vec2 uv)
{
	uv *= PATTERN_ZOOM;
	uv -= PATTERN_ZOOM / 2.0; // Restore center after zooming.
	float distance = 1000000.; // Some value big enough.
	float region = intensity; // Intensity is used as seed.
	for(int i = 0; i < 20; ++i)
	{
		float threshold = getRand(vec2(0, float(i)) + region);
		threshold *= threshold;
		float angle = getRand(vec2(1, float(i)) + region) * PI2;
		vec2 rot = vec2(cos(angle), sin(angle));
		if (dot(uv, rot) < threshold)
			region += pow(2., float(i));
		else
			region -= pow(2., float(i));
		float currDist = abs(dot(uv, rot) - threshold);
		distance = min(currDist, distance);
	}
	return vec2(distance, region);
}

void main()
{
	vec2 res = getPattern(TexCoord0);

	vec2 regionShift = vec2(
		getRand(vec2(0., res.y)) - 0.5,
		getRand(vec2(1., res.y)) - 0.5);
	regionShift *= MAX_SHIFT; // Limit shift.

	vec2 regionCoord = TexCoord0 + regionShift;
	regionCoord = (regionCoord - 0.5) * ZOOM + 0.5;
	vec4 color = texture2D(tex, regionCoord);

	float distanceToBorder = res.x < 0.2 ? 1.0 - 5.0 * res.x : 0.0;
	color.rgb *= pow(1. - distanceToBorder, 0.1); // Highlight borders.

	gl_FragColor = color;
}

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