// actually core in GL 4.3
#extension GL_ARB_texture_query_levels : enable

#include "inc/uniforms.glsl"
#include "inc/utils.glsl"
#line 3

#ifdef VERTEX

layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
// normal
layout(location=3) in vec2 in_UV;
out vec4 ex_Color;
out vec2 ex_UV;

void main()
{
	ex_Color = in_Color;
	ex_UV = in_UV;
	gl_Position = in_Position;
}

#endif

#ifdef FRAGMENT

vec3 filmicTonemap(vec3 c) {
	vec3 x = max(vec3(0.0), c - vec3(0.004));
	vec3 correct = (x*(6.2*x+vec3(.5)))/(x*(6.2*x+vec3(1.7))+vec3(0.06));
	return pow(correct, vec3(2.2));	// the formula includes gamma correction
}

in vec4 ex_Color;
in vec2 ex_UV;

layout(location=0) out vec4 out_Color;

#include "inc/buffers.glsl"

uniform sampler2D glassTex;
uniform sampler2D vingette;

uniform vec4 fogColor;
uniform float fogExponent;
uniform float p_white;
uniform float p_black;

uniform float dirtNoise;
uniform float bloomNoise;
uniform int bloomSamples;

uniform float p_radial_bloom;
uniform float p_radial_blur;
uniform float p_invert;

#define USE_FILMIC_TONEMAP
#define USE_FXAA
#define USE_BLOOM
#define USE_SATURATION_THRESHOLD
#define USE_DIRTY_GLASS
#define USE_VINGETTE
#define USE_RADIAL_BLUR
#define PARTYVERSION

#include "inc/fxaa.glsl"
#line 37

void main()
{
	vec2 resolution = textureSize(colorbuffer, 0);
	vec2 uv = ex_UV;
	
	#ifdef USE_FXAA
	vec4 col = applyFXAA(uv * resolution.xy, colorbuffer, resolution.xy);
	#else
	vec4 col = texture(colorbuffer, ex_UV);
	#endif
	
	#ifdef USE_RADIAL_BLUR
	int iters=int(64*sqrt(abs(p_radial_blur)) *max(1.,(sqrt(length(ex_UV-0.5)*4.)*2+min(1.,max(0.,p_radial_blur-0.03)*3.)))-11);
	iters=max(0,iters);
	for(int i=0;i<iters;i++){
		//vec2 subpoffset=vec2(noise(vec3(ex_UV,p_time+i)),noise(vec3(ex_UV,p_time*0.3+i)))-0.5;
		//subpoffset*=1.5/textureSize(colorbuffer,0);
		col+=texture(colorbuffer, (ex_UV-0.5)*(1.-p_radial_blur*(0.5*(noise(vec3(ex_UV+i,p_time))-0.1)))+0.5);
		}
	col*=1./(iters+1);
	#endif
	
	#ifdef USE_VINGETTE
	col.rgb = mix(col.rgb, texture(bloombuffer ,ex_UV).rgb*5.0, texture(vingette, ex_UV).r);
	#endif
	
	/*
	float depth = texture(depthbuffer, ex_UV).r;
	col.rgb = mix(col.rgb, fogColor.rgb, pow(depth, fogExponent) * fogColor.a);
	*/
	
	#ifdef USE_BLOOM
	for (float i = 0.0 ; i < 5.0 ; i++) {
		for(int j=0;j<bloomSamples;j++){
			vec2 offset=vec2(noise(vec3(ex_UV,p_time+i+j)),noise(vec3(ex_UV,p_time*0.3+i+j)));
			offset=(offset-0.5)*2.0;
			vec2 pos = ((ex_UV+offset*bloomNoise*sqrt(i+1))-0.5)*(1.-p_radial_bloom*(0.5*(noise(vec3(i,j,p_time))-0.1)))+0.5;
			col.rgb += (1.0/(i*0.5+1.0))*textureLod(bloombuffer, pos, i*1.0).rgb/bloomSamples;
		}
	}
	#endif

	
	#ifdef USE_DIRTY_GLASS
	vec2 offset=vec2(noise(vec3(ex_UV,p_time)),noise(vec3(ex_UV,p_time*0.3)));
	offset=(offset-0.5)*2.;
	int level=textureQueryLevels(bloombuffer);
	vec3 lowest = textureLod(bloombuffer, ex_UV+offset*dirtNoise, level*0.8).rgb;
	//float brite = vec3(dot(lowest, vec3(0.2125, 0.72, 0.07)));
	float glass = texture(glassTex, ex_UV).r;
	col.rgb += glass * lowest * 1.0;
	#endif
	
	
	#ifdef USE_FILMIC_TONEMAP
	col.rgb = filmicTonemap(col.rgb);
	#endif
	
	#ifdef USE_SATURATION_THRESHOLD
	vec3 hsv = rgb2hsv(col.rgb);
	float Y = pow(hsv.y, 32.0) * pow(hsv.z, 2.0);
	col.rgb = mix(col.rgb, vec3(Y*1.2), min(Y, 1.0));
	#endif
	

	col.rgb = mix(col.rgb, vec3(1.0), p_white);
	col.rgb = mix(col.rgb, vec3(0.0), p_black);
	
	if (p_invert > 0.0) {
	col.rgb = vec3(1.0-col.rgb);
	}
	
	#ifdef PARTYVERSION
	col.rgb += vec3(0.09); // partybrite
	#endif
	
	out_Color = col; 
} 

#endif