/*
   Hyllian's 5xBR v2 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.

*/

const static float3 dtt = float3(65536,255,1);

float reduce(float3 color)
{
	return dot(color, dtt);
}

struct input
{
	float2 video_size;
	float2 texture_size;
	float2 output_size;
        float frame_count;
        float frame_direction;
	float frame_rotation;
};


struct out_vertex {
	float4 position : POSITION;
	float4 color    : COLOR;
	float2 texCoord : TEXCOORD0;
	float4 t1 : TEXCOORD1;
	float4 t2 : TEXCOORD2;
	float4 t3 : TEXCOORD3;
	float4 t4 : TEXCOORD4;
};

/*    VERTEX_SHADER    */
out_vertex main_vertex
(
	float4 position	: POSITION,
	float4 color	: COLOR,
	float2 texCoord : TEXCOORD0,

   	uniform float4x4 modelViewProj,
	uniform input IN
)
{
	out_vertex OUT;

	OUT.position = mul(modelViewProj, position);
	OUT.color = color;

	float2 ps = float2(1.0/IN.texture_size.x, 1.0/IN.texture_size.y);
	float dx = ps.x;
	float dy = ps.y;

	OUT.texCoord = texCoord;
	OUT.t1.xy = texCoord + float2(-dx,  0);
	OUT.t2.xy = texCoord + float2( dx,  0);
	OUT.t3.xy = texCoord + float2(  0,-dy);
	OUT.t4.xy = texCoord + float2(  0, dy);
	OUT.t1.zw = texCoord + float2(-dx,-dy);
	OUT.t2.zw = texCoord + float2(-dx, dy);
	OUT.t3.zw = texCoord + float2( dx,-dy);
	OUT.t4.zw = texCoord + float2( dx, dy);

	return OUT;
}

#define BR_FILTER(b, c, d, e, f, g, h, i, Ao, Bo, Co, Ax, Bx, Cx, Ay, By, Cy, H)\
	if ( e!=h && h==f && ( (e!=i && (e!=b || e!=d || f!=b && f!=c || h!=d && h!=g))\
		|| (e==g && (i==h || e==d || h!=d))\
		|| (e==c && (i==h || e==b || f!=b))\
	      ))\
		{\
			if ((Ao*fp.y+Bo*fp.x > Co) || (e==c && e==d && h==g && (Ax*fp.y+Bx*fp.x > Cx)) || (e==g && e==b && f==c && (Ay*fp.y+By*fp.x > Cy)))\
				res = H;\
		}\

/*    FRAGMENT SHADER    */
float4 main_fragment(in out_vertex VAR, uniform sampler2D decal : TEXUNIT0, uniform input IN) : COLOR
{
	float2 fp = frac(VAR.texCoord*IN.texture_size);

	float3 A = tex2D(decal, VAR.t1.zw).xyz;
	float3 B = tex2D(decal, VAR.t3.xy).xyz;
	float3 C = tex2D(decal, VAR.t3.zw).xyz;
	float3 D = tex2D(decal, VAR.t1.xy).xyz;
	float3 E = tex2D(decal, VAR.texCoord).xyz;
	float3 F = tex2D(decal, VAR.t2.xy).xyz;
	float3 G = tex2D(decal, VAR.t2.zw).xyz;
	float3 H = tex2D(decal, VAR.t4.xy).xyz;
	float3 I = tex2D(decal, VAR.t4.zw).xyz;

	float a = reduce(A);
	float b = reduce(B);
	float c = reduce(C);
	float d = reduce(D);
	float e = reduce(E);
	float f = reduce(F);
	float g = reduce(G);
	float h = reduce(H);
	float i = reduce(I);	


	float3 res = E;

	BR_FILTER(b, c, d, e, f, g, h, i,  1.0,  1.0,  1.5,  1.0,  0.5,  1.0,  1.0,  2.0,  2.0, H);
	BR_FILTER(d, a, h, e, b, i, f, c, -1.0,  1.0,  0.5, -1.0,  2.0,  1.0, -1.0,  0.5,  0.0, F);
	BR_FILTER(h, g, f, e, d, c, b, a, -1.0, -1.0, -0.5, -1.0, -0.5, -0.5, -1.0, -2.0, -1.0, B);
	BR_FILTER(f, i, b, e, h, a, d, g,  1.0, -1.0,  0.5,  1.0, -2.0,  0.0,  1.0, -0.5,  0.5, D);

	return float4(res, 1.0);
}
