/*
   Hyllian's 5xBR v3.7a Shader
   
   Copyright (C) 2011 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 tex0;
uniform vec4 OGL2Param;
uniform vec4 OGL2Size;
uniform vec4 OGL2InvSize;

const float coef = 2.0;

vec4 MatD(vec4 a, vec4 b)
{
vec4 temp = a - b;
return temp*temp;
}

bvec4 xBR(vec4 e, vec4 c, vec4 g, vec4 i, vec4 h5, vec4 f4, vec4 h, vec4 f, vec4 d, vec4 i5, vec4 i4, vec4 b)
{
vec4 weighted_distanceR = MatD(e,c) + MatD(e,g) + MatD(i,h5) + MatD(i,f4) + 4.0*MatD(h,f);
vec4 weighted_distanceB = MatD(h,d) + MatD(h,i5) + MatD(f,i4) + MatD(f,b) + 4.0*MatD(e,i);
return lessThan(weighted_distanceR - weighted_distanceB,vec4(0.0)); 
}

float toGray(vec3 e1)
{
return dot(vec3(14.0, 28.0, 5.0),e1);
}

void main (void)
{
vec2 Size = vec2(1024.0,512.0);
vec2 fp = fract(gl_TexCoord[2].yw*Size);

//    A1 B1 C1
// A0  A  B  C C4
// D0  D  E  F F4
// G0  G  H  I I4
//    G5 H5 I5

vec3 A1 = texture2D(tex0, gl_TexCoord[0].xw).rgb;
vec3 B1 = texture2D(tex0, gl_TexCoord[0].yw).rgb;
vec3 C1 = texture2D(tex0, gl_TexCoord[0].zw).rgb;

vec3 A  = texture2D(tex0, gl_TexCoord[1].xw).rgb;
vec3 B  = texture2D(tex0, gl_TexCoord[1].yw).rgb;
vec3 C  = texture2D(tex0, gl_TexCoord[1].zw).rgb;

vec3 D  = texture2D(tex0, gl_TexCoord[2].xw).rgb;
vec3 E  = texture2D(tex0, gl_TexCoord[2].yw).rgb;
vec3 F  = texture2D(tex0, gl_TexCoord[2].zw).rgb;

vec3 G  = texture2D(tex0, gl_TexCoord[3].xw).rgb;
vec3 H  = texture2D(tex0, gl_TexCoord[3].yw).rgb;
vec3 I  = texture2D(tex0, gl_TexCoord[3].zw).rgb;

vec3 G5 = texture2D(tex0, gl_TexCoord[4].xw).rgb;
vec3 H5 = texture2D(tex0, gl_TexCoord[4].yw).rgb;
vec3 I5 = texture2D(tex0, gl_TexCoord[4].zw).rgb;

vec3 A0 = texture2D(tex0, gl_TexCoord[5].xy).rgb;
vec3 D0 = texture2D(tex0, gl_TexCoord[5].xz).rgb;
vec3 G0 = texture2D(tex0, gl_TexCoord[5].xw).rgb;

vec3 C4 = texture2D(tex0, gl_TexCoord[6].xy).rgb;
vec3 F4 = texture2D(tex0, gl_TexCoord[6].xz).rgb;
vec3 I4 = texture2D(tex0, gl_TexCoord[6].xy).rgb;

float fA  = toGray( A);
float fB  = toGray( B);
float fC  = toGray( C);
float fD  = toGray( D);
float fE  = toGray( E);
float fF  = toGray( F);
float fG  = toGray( G);
float fH  = toGray( H);
float fI  = toGray( I);
float fA1 = toGray(A1);
float fB1 = toGray(B1);
float fC1 = toGray(C1);
float fA0 = toGray(A0);
float fC4 = toGray(C4);
float fD0 = toGray(D0);
float fF4 = toGray(F4);
float fG0 = toGray(G0);
float fI4 = toGray(I4);
float fG5 = toGray(G5);
float fH5 = toGray(H5);
float fI5 = toGray(I5);

vec4 b = vec4(fB,fD,fH,fF); 
vec4 c = vec4(fC,fA,fG,fI); 
vec4 d = vec4(fD,fH,fF,fB); 
vec4 e = vec4(fE); 
vec4 f = vec4(fF,fB,fD,fH); 
vec4 g = vec4(fG,fI,fC,fA); 
vec4 h = vec4(fH,fF,fB,fD); 
vec4 i = vec4(fI,fC,fA,fG); 

vec4 i4 = vec4(fI4,fC1,fA0,fG5); 
vec4 i5 = vec4(fI5,fC4,fA1,fG0); 
vec4 h5 = vec4(fH5,fF4,fB1,fD0); 
vec4 f4 = vec4(fF4,fB1,fD0,fH5); 

vec4 Ao = vec4( 1.0,-1.0,-1.0, 1.0);
vec4 Bo = vec4( 1.0, 1.0,-1.0,-1.0);
vec4 Co = vec4( 1.5, 0.5,-0.5, 0.5);
vec4 Ax = vec4( 1.0,-1.0,-1.0, 1.0);
vec4 Bx = vec4( 0.5, 2.0,-0.5,-2.0);
vec4 Cx = vec4( 1.0, 1.0,-0.5, 0.0);
vec4 Ay = vec4( 1.0,-1.0,-1.0, 1.0);
vec4 By = vec4( 2.0, 0.5,-2.0,-0.5);
vec4 Cy = vec4( 2.0, 0.0,-1.0, 0.5);

bvec4 interp_restriction_lv1      = (notEqual(e,f) && notEqual(e,h));
bvec4 interp_restriction_lv2_left = (notEqual(e,g) && notEqual(e,f));
bvec4 interp_restriction_lv2_up   = (notEqual(e,c) && notEqual(e,h));

vec4 fg = MatD(f,g);
vec4 hc = MatD(h,c);

bvec4 edr      = interp_restriction_lv1 && xBR( e, c, g, i, h5, f4, h, f, d, i5, i4, b);
bvec4 edr_left = interp_restriction_lv2_left && lessThanEqual(coef*fg,hc);
bvec4 edr_up   = interp_restriction_lv2_up && greaterThanEqual(fg,coef*hc);

// These inequations define the line below which interpolation occurs.

bvec4 fx      = greaterThan(Ao*fp.y+Bo*fp.x, Co);
bvec4 fx_left = greaterThan(Ax*fp.y+Bx*fp.x, Cx);
bvec4 fx_up   = greaterThan(Ay*fp.y+By*fp.x, Cy);

bvec4 nc = (edr && (fx || edr_left && fx_left || edr_up && fx_up));

bvec4 px = lessThanEqual(MatD(e,f), MatD(e,h));

vec3 res = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : nc.w ? px.w ? H : D : E;

gl_FragColor = vec4(res,1.0);
}