/*
   2xSaI is Copyright (c) 1999-2001 by Derek Liauw Kie Fa. 
 
   xSaI shader merged by 2015 guest(r) - guest.r@gmail.com

   Hyllian's Data Dependent Triangulation Shader


   
Copyright (C) 2011-2012 Hyllian/Jararaca - sergiogdb@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.

*/


uniform sampler2D OGL2Texture;

vec2 size = vec2(2048.0,1024.0);


const vec3 dtt = vec3(65536.0,255.0,1.0);



float reduce(vec3 color)

{

	return dot(color, dtt);

} 


vec3 bilinear(float p, float q, vec3 A, vec3 B, vec3 C, vec3 D)

{

	return ((1-p)*(1-q)*A + p*(1-q)*B + (1-p)*q*C + p*q*D);

} 


const vec2 OGLSize = vec2(1024.0,512.0);
const vec2 OGLInvSize = vec2(1.0/1024.0,1.0/512.0);


float GET_RESULT(float A, float B, float C, float D)
{
    return (sign(abs(A-C)+abs(A-D)) - sign(abs(B-C)+abs(B-D))); 
}

vec3 texture2d (sampler2D OGL2Texture, vec2 texcoord) {
    // Calculating texel coordinates

    vec2 OGL2Pos = texcoord*OGLSize.xy;
    vec2 fp = fract(OGL2Pos);
    vec2 g1 = vec2( OGLInvSize.x,OGLInvSize.y);
    vec2 g2 = vec2(-OGLInvSize.x,OGLInvSize.y);

    if (fp.x >= 0.50 && fp.y < 0.50) g2*=-1.0;

    vec2 pC4 = floor(OGL2Pos)/OGLSize.xy + 0.5*OGLInvSize;
    vec2 pC8 = pC4 + g1;
    vec2 pC0 = pC4 - g1;

    vec2 p04 = pC4 - 0.5*g1;
    vec2 pC3 = p04 + 0.5*g2;
    vec2 pC1 = pC3 - g2;
    vec2 pC5 = pC1 + g1;
    vec2 pC7 = pC3 + g1;


    // Reading the texels

    vec3 C0 = texture2D(OGL2Texture,pC0   ).xyz; 
    vec3 C1 = texture2D(OGL2Texture,pC1   ).xyz;
    vec3 C2 = texture2D(OGL2Texture,pC4-g2).xyz;
    vec3 C3 = texture2D(OGL2Texture,pC3   ).xyz;
    vec3 C4 = texture2D(OGL2Texture,pC4   ).xyz;
    vec3 C5 = texture2D(OGL2Texture,pC5   ).xyz;
    vec3 D4 = texture2D(OGL2Texture,pC8-g2).xyz;
    vec3 C6 = texture2D(OGL2Texture,pC4+g2).xyz;
    vec3 C7 = texture2D(OGL2Texture,pC7   ).xyz;
    vec3 C8 = texture2D(OGL2Texture,pC8   ).xyz;
    vec3 D5 = texture2D(OGL2Texture,pC5+g1).xyz;
    vec3 D0 = texture2D(OGL2Texture,pC7+g2).xyz;
    vec3 D1 = texture2D(OGL2Texture,pC8+g2).xyz;
    vec3 D2 = texture2D(OGL2Texture,pC7+g1).xyz;
    vec3 p10,p11;

    float c0 = reduce(C0);float c1 = reduce(C1);
    float c2 = reduce(C2);float c3 = reduce(C3);
    float c4 = reduce(C4);float c5 = reduce(C5);
    float c6 = reduce(C6);float c7 = reduce(C7);
    float c8 = reduce(C8);float d0 = reduce(D0);
    float d1 = reduce(D1);float d2 = reduce(D2);
    float d4 = reduce(D4);float d5 = reduce(D5);

    if (c4 == c8) {
        if (c5 != c7) {
            if (((c4 == c3)&&(c7 == d2))||((c4 == c5)&&(c4 == c6)&&(c3 != c7)&&(c7 == d0))) {
                    p10 = C4;
            } else {
                    p10 = 0.5*(C4+C7);
            }
            p11 = C4;
        } else {
            if (c4 == c5) {
                    p10 = C4;
                    p11 = C4;
            } else {
                float r;
                r  = GET_RESULT(c4,c5,c3,c1);
                r -= GET_RESULT(c5,c4,d4,c2);
                r -= GET_RESULT(c5,c4,c6,d1);
                r += GET_RESULT(c4,c5,d5,d2);
                if (r > 0.0) p11 = C4;
                else if (r < 0.0) p11 = C5;
                else p11 = 0.25*(C4+C5+C7+C8);
                p10 = 0.5*(C4+C7);
            }
        }
    } else
        if (c5 == c7) {
            if (((c7 == c6)&&(c4 == c2))||((c7 == c3)&&(c7 == c8)&&(c4 != c6)&&(c4 == c0))) {
                    p10 = C7;
            } else {
                    p10 = 0.5*(C4+C7);
            }
            p11 = C5;
        } else {
            p11 = 0.25*(C4+C5+C7+C8);

            if ((c4 == c5)&&(c4 == c6)&&(c3 != c7)&&(c7 == d0)) {
                    p10 = C4;
            } else if ((c7 == c3)&&(c7 == c8)&&(c4 != c6)&&(c4 == c0)) {
                       p10 = C7;
            } else {
                p10 = 0.5*(C4+C7);
        } 
    }

    // Distributing the final products    
    
    if (fp.x >= 0.5 && fp.y >= 0.5) return p11; else
    if (fp.x <  0.5 && fp.y <  0.5) return  C4; else
    return p10;
} 


void main()
{
	vec2 pos = fract(gl_TexCoord[0].xy*size)-vec2(0.5, 0.5); // pos = pixel position
	
	vec2 dir = sign(pos); // dir = pixel direction

	vec2 g1 = dir*gl_TexCoord[1].xy;

	vec2 g2 = dir*gl_TexCoord[1].zw; 

	vec3 A = texture2d(OGL2Texture, gl_TexCoord[0].xy          ).xyz; 
	vec3 B = texture2d(OGL2Texture, gl_TexCoord[0].xy + g1     ).xyz; 
	vec3 C = texture2d(OGL2Texture, gl_TexCoord[0].xy      + g2).xyz; 
	vec3 D = texture2d(OGL2Texture, gl_TexCoord[0].xy + g1 + g2).xyz; 

	float a = reduce(A);

	float b = reduce(B);

	float c = reduce(C);

	float d = reduce(D); 

	float p = abs(pos.x);
	
	float q = abs(pos.y);



	float k = distance(pos,g1);

	float l = distance(pos,g2); 

	if (abs(a-d) < abs(b-c))

	{

		if (k < l)

		{

			C = A + D - B;

		}

		else if (k >= l)

		{

			B = A + D - C;

		}

	}

	else if (abs(a-d) > abs(b-c))

	{

		D = B + C - A;

	} 

	gl_FragColor.xyz=bilinear(p, q, A, B, C, D);
}