/*
   Hyllian's 5xBR 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;
	float2 texCoord : TEXCOORD0;
	float4 t1 : TEXCOORD1;
};

/*    VERTEX_SHADER    */
out_vertex main_vertex
(
	float4 position	: POSITION,
	float2 texCoord1 : TEXCOORD0,

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

	OUT.position = mul(modelViewProj, position);

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

	// This line fix a bug in ATI cards.
	float2 texCoord = texCoord1 + float2(0.0000001, 0.0000001);

	OUT.texCoord = texCoord;
	OUT.t1.xy = float2(  0,-dy); // B
	OUT.t1.zw = float2(-dx,  0); // D

	return OUT;
}

/*    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);

	float2 g1 = VAR.t1.xy*(step(0.5,fp.x)+step(0.5, fp.y)-1) + VAR.t1.zw*(step(0.5,fp.x) - step(0.5, fp.y));
	float2 g2 = VAR.t1.xy*(step(0.5,fp.y) - step(0.5, fp.x)) + VAR.t1.zw*(step(0.5,fp.x)+step(0.5, fp.y)-1);

	float3 B = tex2D(decal, VAR.texCoord +g1   ).xyz;
	float3 C = tex2D(decal, VAR.texCoord +g1-g2).xyz;
	float3 D = tex2D(decal, VAR.texCoord    +g2).xyz;
	float3 E = tex2D(decal, VAR.texCoord       ).xyz;
	float3 F = tex2D(decal, VAR.texCoord    -g2).xyz;
	float3 G = tex2D(decal, VAR.texCoord -g1+g2).xyz;
	float3 H = tex2D(decal, VAR.texCoord -g1   ).xyz;
	float3 I = tex2D(decal, VAR.texCoord -g1-g2).xyz;

	float3 E14 = E;
	float3 E19 = E;
	float3 E24 = E;

		
	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);	
	
	
	if (h==f && h!=e && ( e==g && (h==i || e==d) || e==c && (h==i || e==b) ))
	{
		E24 = F;
		E19 = lerp(E19, F, 0.875);	
		E14 = lerp(E14, F, 0.125);
	}
	
	float3 res;

	res = (fp.x < 0.4) ? ((fp.x < 0.2) ? ((fp.y < 0.2) ? E24: (fp.y < 0.4) ? E19: (fp.y < 0.6) ? E14 : (fp.y < 0.8) ? E19 : E24) : ((fp.y < 0.2) ? E19: (fp.y < 0.4) ? E14: (fp.y < 0.6) ? E   : (fp.y < 0.8) ? E14 : E19))	: ((fp.x < 0.8) ? ((fp.x < 0.6) ? ((fp.y < 0.2) ? E14: (fp.y < 0.4) ? E  : (fp.y < 0.6) ? E   : (fp.y < 0.8) ? E   : E14) : ((fp.y < 0.2) ? E19: (fp.y < 0.4) ? E14: (fp.y < 0.6) ? E   : (fp.y < 0.8) ? E14 : E19) ) :	((fp.y < 0.2) ? E24: (fp.y < 0.4) ? E19: (fp.y < 0.6) ? E14 : (fp.y < 0.8) ? E19 : E24) );

	return float4(res, 1.0);
}
