// Gendither
// 
// 	Copyright (C) 2013-2014 leilei
// 
// 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.

/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
   - FX11 compilers
*/

#include "../../compat_includes.inc"
uniform COMPAT_Texture2D(decal) : TEXUNIT0;
uniform float4x4 modelViewProj;

struct out_vertex
{
	float4 position : COMPAT_POS;
	float2 texCoord : TEXCOORD0;
};

out_vertex main_vertex(COMPAT_IN_VERTEX)
{
#ifdef HLSL_4
	float4 position = VIN.position;
	float2 texCoord = VIN.texCoord;
#endif
	out_vertex OUT;
	OUT.position = mul(modelViewProj, position);
	OUT.texCoord = texCoord;
	
	return OUT;
}

// This table is a lazy jailbar pattern
float erroredtable[16] = {
	0,1,0,1,   
	16,15,16,15,
	0,1,0,1,   
	16,15,16,15
};

float4 gendither(float2 texture_size, float2 texCoord, COMPAT_Texture2D(decal))
{

	float4 final = COMPAT_SamplePoint(decal, texCoord);

	float2 res;
	res.x = texture_size.x;
	res.y = texture_size.y;
	
	float2 ditheu = texCoord.xy * res.xy;

	ditheu.x = texCoord.x * res.x;
	ditheu.y = texCoord.y * res.y;

	//
	// Dither
	//

	int ditdex = 	int(fmod(ditheu.x, 4.0)) * 4 + int(fmod(ditheu.y, 4.0)); // 4x4!
	int3 color;
	int3 colord;
	color.r = final.r * 224;
	color.g = final.g * 224;
	color.b = final.b * 224;
	int yeh = 0;
	int ohyes = 0;

	// looping through a lookup table matrix
	//for (yeh=ditdex; yeh<(ditdex+16); yeh++) ohyes = pow(erroredtable[yeh-15], 0.72f);
	// Unfortunately, RetroArch doesn't support loops so I have to unroll this. =(

	if (yeh++==ditdex) ohyes = erroredtable[0];
	else if (yeh++==ditdex) ohyes = erroredtable[1];
	else if (yeh++==ditdex) ohyes = erroredtable[2];
	else if (yeh++==ditdex) ohyes = erroredtable[3];
	else if (yeh++==ditdex) ohyes = erroredtable[4];
	else if (yeh++==ditdex) ohyes = erroredtable[5];
	else if (yeh++==ditdex) ohyes = erroredtable[6];
	else if (yeh++==ditdex) ohyes = erroredtable[7];
	else if (yeh++==ditdex) ohyes = erroredtable[8];
	else if (yeh++==ditdex) ohyes = erroredtable[9];
	else if (yeh++==ditdex) ohyes = erroredtable[10];
	else if (yeh++==ditdex) ohyes = erroredtable[11];
	else if (yeh++==ditdex) ohyes = erroredtable[12];
	else if (yeh++==ditdex) ohyes = erroredtable[13];
	else if (yeh++==ditdex) ohyes = erroredtable[14];
	else if (yeh++==ditdex) ohyes = erroredtable[15];

	colord.r = color.r + ohyes;
	colord.g = color.g + ohyes;
	colord.b = color.b + ohyes;
	final.rgb = colord.rgb * 0.003921568627451; // divide by 255, i don't trust em

	//
	// Reduce color depth
	//

	float3 why = float3(1, 1, 1);
	float3 reduceme = float3(1, 1, 1);
	float radooct = 5;	// 32 is usually the proper value

	reduceme.r = pow(final.r, why.r);  
	reduceme.r *= radooct;	
	reduceme.r = int(floor(reduceme.r));	
	reduceme.r /= radooct; 
	reduceme.r = pow(reduceme.r, why.r);

	reduceme.g = pow(final.g, why.g);  
	reduceme.g *= radooct;	
	reduceme.g = int(floor(reduceme.g));	
	reduceme.g /= radooct; 
	reduceme.g = pow(reduceme.g, why.g);

	reduceme.b = pow(final.b, why.b);  
	reduceme.b *= radooct;	
	reduceme.b = int(floor(reduceme.b));	
	reduceme.b /= radooct; 
	reduceme.b = pow(reduceme.b, why.b);

	//
	// Brightness cap
	//

	if (reduceme.r > 224) reduceme.r = 224;
	if (reduceme.g > 224) reduceme.g = 224;
	if (reduceme.b > 224) reduceme.b = 224;

	final.rgb = reduceme.rgb;
	
   return final;
}

float4 main_fragment(COMPAT_IN_FRAGMENT) : COMPAT_Output
{
	return gendither(COMPAT_texture_size, VOUT.texCoord, decal);
}
COMPAT_END
