uniform sampler2D color_lut;
uniform sampler1D color_grad;
uniform sampler2D distort_lut;
uniform sampler2D noise_lut;

uniform float lut_fade;
uniform vec3 distortParams; // freq, time, amount
uniform vec2 gammaParams; // exposure, gamma
uniform vec3 noiseParams; // offset.xy, amount
uniform vec2 invViewport;

vec2 distort_uv(in vec2 uv)
{
	vec2 offs;

	offs.x = textureLod(distort_lut, vec2(uv.y*distortParams.x + distortParams.y, 0.0), 0.0).x*distortParams.z * 0.01;
	offs.x *= (sin(uv.y*3.14*distortParams.x + 3.14*distortParams.y)*2.0 - 1.0)*distortParams.z;
	offs.y = (sin(uv.x*3.14*distortParams.x + 3.14*distortParams.y)*2.0 - 1.0)*distortParams.z*0.01;
	float falloff = smoothstep(0.75, 1.0, distance(uv, vec2(0.5))*2.0);
	return uv + offs*falloff;
}

vec3 filmic_tonemap(in vec3 x)
{
	const float A = 0.15;
	const float B = 0.50;
	const float C = 0.10;
	const float D = 0.20;
	const float E = 0.02;
	const float F = 0.30;
	const float W = 11.2;
	return ( (x * (x*A + vec3(C*B)) + vec3(D*E)) / (x*(x*A + vec3(B)) + vec3(D*F))) - vec3(E/F);
}

// used by color_lookup()
vec4 color_correction(in vec4 color)
{
#if 1
	color *= gammaParams.x;
	color.rgb = pow(color.rgb, gammaParams.yyy);
#else
	color.rgb = filmic_tonemap(color.rgb*16.0*gammaParams.x);
	color.rgb *= 1.0 / filmic_tonemap(vec3(11.2)).r;
	color.rgb = pow(color.rgb, gammaParams.yyy);
#endif
	return color;
}

vec4 noise_lookup()
{
	vec2 uv = gl_FragCoord.xy * invViewport;
	float n = (texture(noise_lut, uv + noiseParams.xy).x*2.0 - 1.0)*noiseParams.z;
	return vec4(n, n, n, 1.0);
}

vec4 color_lum(in vec4 color)
{
	float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114));
	return texture(color_lut, vec2(lum));
}

vec4 color_gradient(in vec4 color)
{
	vec4 c;
	c.r = texture(color_grad, color.r).r;
	c.g = texture(color_grad, color.g).g;
	c.b = texture(color_grad, color.b).b;
	c.a = color.a;
	return c;
}


vec4 color_lookup(in vec4 color, in vec2 uv)
{
	float falloff = smoothstep(0.4, 1.0, distance(uv, vec2(0.5))*1.4);
	vec4 cl = color_lum(color);
	vec4 cg = color_gradient(color);
	vec4 c = mix(cg, cl, lut_fade*falloff);
	return color_correction(c) + noise_lookup();
}
