//##############################################################//
//						                //
//       AA Shader 4.o + colors shader - coded by guest(r)      //
//		     part of code by ShadX		        //
//##############################################################// 



/*
   shader levels: 1 - normal
                  2 - bloom
                  3 - natural
                  4 - natural + bloom

   NOTE!!! Turn fullscreen smoothing OFF.	
*/


float bloom   = 0.50;
float natural = 1.15;

uniform sampler2D OGL2Texture;
uniform vec4 OGL2Param;

const vec3 dt = vec3(1.0,1.0,1.0);


const mat3 RGBtoYIQ = mat3(0.299, 0.596, 0.212, 
                           0.587,-0.275,-0.523, 
                           0.114,-0.321, 0.311);

const mat3 YIQtoRGB = mat3(1.000, 1.000, 1.000,
                           0.955,-0.271,-1.108,
                           0.619,-0.646, 1.705);


vec4 yx = vec4(1.0/4096,1.0/2048,-1.0/4096,-1.0/2048);

vec3 texture2d (vec2 texcoord) {

	vec3 s00 = texture2D(OGL2Texture, texcoord + yx.zw).xyz; 
	vec3 s20 = texture2D(OGL2Texture, texcoord + yx.xw).xyz; 
	vec3 s22 = texture2D(OGL2Texture, texcoord + yx.xy).xyz; 
	vec3 s02 = texture2D(OGL2Texture, texcoord + yx.zy).xyz; 

	float m1=dot(abs(s00-s22),dt)+0.001;
	float m2=dot(abs(s02-s20),dt)+0.001;

	return .5*(m2*(s00+s22)+m1*(s02+s20))/(m1+m2);
}


void main()
{
	// Calculating texel coordinates
	vec2 size     = vec2(4096.0,2048.0);
	vec2 inv_size = vec2(1.0/4096.0,1.0/2048.0);
	
	vec2 OGL2Pos = gl_TexCoord[0].xy * size;
	vec2 fp = fract(OGL2Pos);
	vec2 dx = vec2(inv_size.x,0.0);
	vec2 dy = vec2(0.0, inv_size.y);
	vec2 g1 = vec2(inv_size.x,inv_size.y);
	vec2 g2 = vec2(-inv_size.x,inv_size.y);
	
	vec2 pC4 = floor(OGL2Pos) * inv_size;	
	
	// Reading the texels
	vec3 C0 = texture2d(pC4 - g1); 
	vec3 C1 = texture2d(pC4 - dy);
	vec3 C2 = texture2d(pC4 - g2);
	vec3 C3 = texture2d(pC4 - dx);
	vec3 C4 = texture2d(pC4     );
	vec3 C5 = texture2d(pC4 + dx);
	vec3 C6 = texture2d(pC4 + g2);
	vec3 C7 = texture2d(pC4 + dy);
	vec3 C8 = texture2d(pC4 + g1);
	
	vec3 ul, ur, dl, dr;
	float m1, m2;
	
	m1 = dot(abs(C0-C4),dt)+0.001;
	m2 = dot(abs(C1-C3),dt)+0.001;
	ul = (m2*(C0+C4)+m1*(C1+C3))/(m1+m2);  
	
	m1 = dot(abs(C1-C5),dt)+0.001;
	m2 = dot(abs(C2-C4),dt)+0.001;
	ur = (m2*(C1+C5)+m1*(C2+C4))/(m1+m2);
	
	m1 = dot(abs(C3-C7),dt)+0.001;
	m2 = dot(abs(C6-C4),dt)+0.001;
	dl = (m2*(C3+C7)+m1*(C6+C4))/(m1+m2);
	
	m1 = dot(abs(C4-C8),dt)+0.001;
	m2 = dot(abs(C5-C7),dt)+0.001;
	dr = (m2*(C4+C8)+m1*(C5+C7))/(m1+m2);
	
	vec3 c11 = 0.5*((dr*fp.x+dl*(1-fp.x))*fp.y+(ur*fp.x+ul*(1-fp.x))*(1-fp.y));

	inv_size = vec2(0.00048828125, 0.0009765625);

	dx  = vec2(inv_size.x,0.0);
	dy  = vec2(0.0,inv_size.y);
	g1  = vec2( inv_size.x,inv_size.y);
	g2  = vec2(-inv_size.x,inv_size.y);
	pC4 = gl_TexCoord[0].xy;
  
	C0 = texture2D(OGL2Texture,pC4-g1).xyz; 
	C1 = texture2D(OGL2Texture,pC4-dy).xyz;
	C2 = texture2D(OGL2Texture,pC4-g2).xyz;
	C3 = texture2D(OGL2Texture,pC4-dx).xyz;
	C4 = texture2D(OGL2Texture,pC4   ).xyz;
	C5 = texture2D(OGL2Texture,pC4+dx).xyz;
	C6 = texture2D(OGL2Texture,pC4+g2).xyz;
	C7 = texture2D(OGL2Texture,pC4+dy).xyz;
	C8 = texture2D(OGL2Texture,pC4+g1).xyz;
 
	vec3 mn1 = min(min(C0,C1),C2);
	vec3 mn2 = min(min(C3,C4),C5);
	vec3 mn3 = min(min(C6,C7),C8);
	vec3 mx1 = max(max(C0,C1),C2);
	vec3 mx2 = max(max(C3,C4),C5);
	vec3 mx3 = max(max(C6,C7),C8);
 
	mn1 = min(min(mn1,mn2),mn3);
	mx1 = max(max(mx1,mx2),mx3);
 
	vec3 dif1 = abs(c11-mn1) + 0.001*dt;
	vec3 dif2 = abs(c11-mx1) + 0.001*dt;
 
//	float filterparam = 2.0; 
 
	vec3 dif = max(max(ul,ur),max(dl,dr))-min(min(ul,ur),min(dl,dr));	
	float filterparam = clamp(4.0*max(dif.x,max(dif.y,dif.z)),1.0,2.0);
 

	dif1=vec3(pow(dif1.x,filterparam),pow(dif1.y,filterparam),pow(dif1.z,filterparam));
	dif2=vec3(pow(dif2.x,filterparam),pow(dif2.y,filterparam),pow(dif2.z,filterparam));
 
	c11.r = (dif1.x*mx1.x + dif2.x*mn1.x)/(dif1.x + dif2.x);
	c11.g = (dif1.y*mx1.y + dif2.y*mn1.y)/(dif1.y + dif2.y);
	c11.b = (dif1.z*mx1.z + dif2.z*mn1.z)/(dif1.z + dif2.z);

	if  (OGL2Param.z < 2.0) natural = 1.0;
	c11=RGBtoYIQ*c11;
	c11=vec3(pow(c11.x,natural),c11.yz*natural);
	c11=YIQtoRGB*c11;
	float k1 = length(c11); bloom = mod(OGL2Param.z,2)*bloom;
	c11 = (1.0-bloom)*c11 + bloom*mix(k1,normalize(vec2(k1*k1,0.82)).x*1.74,0.577*k1)*normalize(c11);
 
	gl_FragColor.xyz = c11;
}
