_CalcLum1.vsh
{
	uniform	mat4	u_ModelViewProjectionMatrix;
	in	vec3	attr_Position;
	in	vec2	attr_texCoords;
	out	vec2	texCoord;
	void main(void)
	{
		texCoord = attr_texCoords;
		gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
	}
}

_CalcLum1.fsh
{
	uniform sampler2DRect	u_HDR_Buffer;
	in	vec2	texCoord;
	out	float	fragData;
	void main(void)
	{
		vec3 c = texture(u_HDR_Buffer, texCoord).rgb;
		fragData = log2(clamp(dot(vec3(0.2125, 0.7154, 0.0721), c), 0.0001, 9999.9));

	}
}


_CalcLum2.vsh
{
	uniform	mat4	u_ModelViewProjectionMatrix;
	in	vec3	attr_Position;
	in	vec2	attr_texCoords;
	out	vec2	texCoord;
	void main(void)
	{
		texCoord = attr_texCoords;
		gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
	}
}

_CalcLum2.fsh
{
	uniform sampler2D	u_HDR_Buffer;
	uniform vec4		u_texSteps;
	in	vec2	texCoord;
	out	float	fragData;
	void main(void)
	{
		float c;

		c  = textureLod(u_HDR_Buffer, texCoord + u_texSteps.xx, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.yx, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.zx, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.wx, 0.0).r;

		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.xy, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.yy, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.zy, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.wy, 0.0).r;

		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.xz, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.yz, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.zz, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.wz, 0.0).r;

		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.xw, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.yw, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.zw, 0.0).r;
		c += textureLod(u_HDR_Buffer, texCoord + u_texSteps.ww, 0.0).r;

		fragData = c * 0.0625;
	}
}


_ToneMap.vsh
{
	include generic_vertex.vsh
}

_ToneMap.fsh
{
	uniform sampler2DRect	u_ScreenBuffer;
	uniform sampler2D	u_AvgLumBuffer;
	uniform sampler2D	u_PrevAvgLumBuffer;
	uniform vec2		u_autoExposureMinMax;
	uniform vec3		u_toneMinAvgMaxLevel;
	uniform float		u_backlerp;
	out	vec4	fragData;

	vec3 uncharted2Tonemap(in vec3 x)
	{
		#define	A	0.15
		#define	B	0.50
		#define	C	0.10
		#define	D	0.20
		#define	E	0.02
		#define	F	0.30
		return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
	}

	void main(void)
	{
		vec4 color = texture(u_ScreenBuffer, gl_FragCoord.xy);
		float minAvgMax = textureLod(u_AvgLumBuffer, vec2(0.5), 0.0).r;
		float prevMinAvgMax = textureLod(u_PrevAvgLumBuffer, vec2(0.5), 0.0).r;

		// adaptation
		minAvgMax = mix(prevMinAvgMax, minAvgMax, u_backlerp);

		float logMinAvgMaxLum = clamp(minAvgMax, -u_autoExposureMinMax.y, -u_autoExposureMinMax.x);
		float avgLum = exp2(logMinAvgMaxLum);

		color.rgb *= u_toneMinAvgMaxLevel.y / avgLum;
		color.rgb = max(vec3(0.0), color.rgb - vec3(u_toneMinAvgMaxLevel.x));

		vec3 fWhite = 1.0 / uncharted2Tonemap(vec3(u_toneMinAvgMaxLevel.z - u_toneMinAvgMaxLevel.x));
		color.rgb = uncharted2Tonemap(color.rgb) * fWhite;
	
		fragData = color;
	}
}
