uniform sampler2D tex;

uniform float shoulderStrength;
const float linearStrength = 0.3;
const float linearAngle = 0.1;
uniform float toeStrength;
uniform float toeNumerator;
uniform float toeDenominator;
uniform float linearWhitePoint;

const float screenGamma = 2.2;

uniform float exposure;
uniform float offset;
uniform float gamma;

uniform float gammaCorrect;
uniform float applyTonemap;

vec3 pow(vec3 color, float power)
{
	color.r = pow(color.r, power);
	color.g = pow(color.g, power);
	color.b = pow(color.b, power);

	return color; 
}

vec4 pow(vec4 color, float power)
{
	color.r = pow(color.r, power);
	color.g = pow(color.g, power);
	color.b = pow(color.b, power);
	color.a = pow(color.a, power);

	return color; 
}


float filmicTonemap(float x)
{
	//from
	float mappedX = ((x*(shoulderStrength*x+linearAngle*linearStrength)+toeStrength*toeNumerator));
	mappedX /= (x*(shoulderStrength*x+linearStrength)+toeStrength*toeDenominator);
	mappedX -= toeNumerator/toeDenominator;

	return mappedX;
}

vec3 filmicTonemap(vec3 x)
{
	//from
	vec3 mappedColor = x;
	mappedColor.r = filmicTonemap(mappedColor.r);
	mappedColor.g = filmicTonemap(mappedColor.g);
	mappedColor.b = filmicTonemap(mappedColor.b);

	return mappedColor;
}

void main()
{
	vec4 color = texture2D(tex, gl_TexCoord[0].xy);

	color.rgb += 0.001;	

	color = (1.0-gammaCorrect) * color + gammaCorrect * pow(color, screenGamma);
	
	color.rgb = pow((color.rgb * (1.0 + exposure)) + offset, 1.0/gamma);
//	color.r *=1.5;
//	color.b *= 0.7;
	color.rgb = (1.0-applyTonemap) * color.rgb + applyTonemap * filmicTonemap(color.rgb)/filmicTonemap(linearWhitePoint);

	color = (1.0-gammaCorrect) * color + gammaCorrect * pow(color, 1.0/screenGamma);

	gl_FragColor = color;
}
