/*
   AA Shader 4.o 2D+3D fast shader - coded by guest(r)    

   Copyright (C) 2016 guest(r) - guest.r@gmail.com

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/


// Color variables (please edit them)

const vec3 c_ch = vec3(1.0,1.0,1.0);  //  rgb color channel intensity
const float   a = 1.00 ;              //  saturation  usable values between 0.0...2.0
const float   b = 1.00 ;              //  brightness 
const float   c = 0.00 ;              //  contrast    usable values between 0.0...1.0

const float threshold = 0.02; // 2D-3D algorithm threshold (3D -> 0.0....0.05 -> 2D)


uniform sampler2D OGL2Texture;
uniform vec4 OGL2Size;
uniform vec4 OGL2Param;

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


const   vec2 OGLSize    = vec2( 1024.0, 512.0);
const   vec2 OGLInvSize = vec2( 0.0009765625, 0.001953125); 
const   vec2 dx         = vec2( 0.0009765625, 0.0);
const   vec2 dy         = vec2( 0.0, 0.001953125 );


vec3 SoftAA (sampler2D OGL2Texture, vec2 texcoord) {
	
	float offset = 0.40;
	if (OGL2Size.x > 4096.0) offset = 0.25;

	float x = offset/2048.0;
	float y = offset/1024.0;

	vec4 yx3 = vec4(1.0/4096,1.0/2048,-1.0/4096,-1.0/2048)*offset;

	vec3 c11 = texture2D(OGL2Texture, texcoord).xyz;
	vec3 s00 = texture2D(OGL2Texture, texcoord + yx3.zw).xyz; 
	vec3 s20 = texture2D(OGL2Texture, texcoord + yx3.xw).xyz; 
	vec3 s22 = texture2D(OGL2Texture, texcoord + yx3.xy).xyz; 
	vec3 s02 = texture2D(OGL2Texture, texcoord + yx3.zy).xyz; 
	vec3 c00 = texture2D(OGL2Texture, texcoord + vec2( -x, -y)).xyz; 
	vec3 c22 = texture2D(OGL2Texture, texcoord + vec2(  x,  y)).xyz; 
	vec3 c20 = texture2D(OGL2Texture, texcoord + vec2(  x, -y)).xyz;
	vec3 c02 = texture2D(OGL2Texture, texcoord + vec2( -x,  y)).xyz;
	vec3 c10 = texture2D(OGL2Texture, texcoord + vec2(0.0, -y)).xyz; 
	vec3 c21 = texture2D(OGL2Texture, texcoord + vec2(  x,0.0)).xyz; 
	vec3 c12 = texture2D(OGL2Texture, texcoord + vec2(0.0,  y)).xyz; 
	vec3 c01 = texture2D(OGL2Texture, texcoord + vec2( -x,0.0)).xyz;     

	float d1=dot(abs(c00-c22),dt)+0.001;
	float d2=dot(abs(c20-c02),dt)+0.001;
	float hl=dot(abs(c01-c21),dt)+0.001;
	float vl=dot(abs(c10-c12),dt)+0.001;
	float m1=dot(abs(s00-s22),dt)+0.001;
	float m2=dot(abs(s02-s20),dt)+0.001;

	vec3 t1=(hl*(c10+c12)+vl*(c01+c21)+(hl+vl)*c11)/(3.0*(hl+vl));
	vec3 t2=(d1*(c20+c02)+d2*(c00+c22)+(d1+d2)*c11)/(3.0*(d1+d2));
	
	c11 =.25*(t1+t2+(m2*(s00+s22)+m1*(s02+s20))/(m1+m2));

	return c11; 
}


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

vec3 texture2dd (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);
}


vec3 AA4 (sampler2D OGL2Texture, vec2 texcoord)
{	
	
	// Calculating texel coordinates
	vec2 size     = vec2(4096.0,2048.0);
	vec2 inv_size = vec2(1.0/4096.0,1.0/2048.0);
	
	vec2 OGL2Pos = texcoord * 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 + 0.5*inv_size;	
	
	// Reading the texels
	vec3 C0 = texture2dd(pC4 - g1); 
	vec3 C1 = texture2dd(pC4 - dy);
	vec3 C2 = texture2dd(pC4 - g2);
	vec3 C3 = texture2dd(pC4 - dx);
	vec3 C4 = texture2dd(pC4     );
	vec3 C5 = texture2dd(pC4 + dx);
	vec3 C6 = texture2dd(pC4 + g2);
	vec3 C7 = texture2dd(pC4 + dy);
	vec3 C8 = texture2dd(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));
 
	return c11;
} 


float contrast(float x)
{ 
	float y = x*1.1547-1.0;
	y = (sin(y*1.5707)+1.1)*0.83;
	return (1.0-c)*x + c*y;
}


float diff2D (vec2 coord)
{
	vec3 c00 = texture2D(OGL2Texture, coord + 0.25*(-dx-dy)).xyz; 
	vec3 c20 = texture2D(OGL2Texture, coord + 0.25*( dx-dy)).xyz; 
	vec3 c02 = texture2D(OGL2Texture, coord + 0.25*(-dx+dy)).xyz; 
	vec3 c22 = texture2D(OGL2Texture, coord + 0.25*( dx+dy)).xyz;

	vec3 mn  = min(min(c00,c20),min(c02,c22)); 
	vec3 mx  = max(max(c00,c20),max(c02,c22));

	return dot(mx-mn,dt);
}


void main()
{

	vec2 fp  = fract(gl_TexCoord[0].xy*OGLSize);
	vec2 texcoord = gl_TexCoord[0].xy-fp*OGLInvSize + 0.5*OGLInvSize;
	vec2 locator  = sign(fp-vec2(0.5000000001,0.5000000001));
	float maxdiff = max(max(diff2D(texcoord+locator*dx),diff2D(texcoord+locator*dy)),diff2D(texcoord));

	vec3 color;

	if (maxdiff <= threshold) { color = AA4(OGL2Texture, gl_TexCoord[0].xy).xyz;} 
        else color = SoftAA(OGL2Texture, gl_TexCoord[0].xy).xyz;

	float x = sqrt(dot(color,color));

	color.r = pow(color.r+0.005,a);
	color.g = pow(color.g+0.005,a);
	color.b = pow(color.b+0.005,a);

	gl_FragColor.xyz = contrast(x)*normalize(color*c_ch)*b;
}
