float4x4 mWVP;

#if !defined(SA_UI_SHADER_NORMAL_TYPE) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ONLY) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ALPHA)
float4x4 mWorld;

float4 vScreenSize;
#endif

#define SA_BS_NORMAL				0
#define SA_BS_MULTIPLY				2
#define SA_BS_AVERAGE				7
#define SA_BS_DISSOLVE				8
#define SA_BS_BEHIND				9
#define SA_BS_CLEAR					10
#define SA_BS_COLOR_BURN			11
#define SA_BS_COLOR_DODGE			12
#define SA_BS_OVERLAY				13
#define SA_BS_SOFT_LIGHT			14
#define SA_BS_HARD_LIGHT			15
#define SA_BS_DIFFERENCE			16
#define SA_BS_INVERSE_DIFFERENCE	17
#define SA_BS_EXCLUSION				18
#define SA_BS_OPACITY				19

#define PIXEL_CORRECTION 0.5f

texture DecaleTex;
sampler DecaleSamp = sampler_state
{
    Texture = <DecaleTex>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;

    AddressU = Clamp;
    AddressV = Clamp;
};

#if !defined(SA_UI_SHADER_NORMAL_TYPE) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ONLY) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ALPHA)
texture ScreenTex;
sampler ScreenSamp = sampler_state
{
    Texture = <ScreenTex>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;

    AddressU = Clamp;
    AddressV = Clamp;
};
#endif

struct VS_OUTPUT
{
    float4 Pos			: POSITION;
    float4 Color		: COLOR0;
    float2 Tex			: TEXCOORD0;
#if !defined(SA_UI_SHADER_NORMAL_TYPE) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ONLY) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ALPHA)
	float2 Screen		: TEXCOORD1;
#endif
};

VS_OUTPUT VS(float4 Pos      : POSITION,
             float4 Diffuse  : COLOR0,
             float2 Texcoord : TEXCOORD0)
{
	VS_OUTPUT Out = (VS_OUTPUT)0;
	
	Out.Pos = mul(Pos, mWVP);
	Out.Tex = Texcoord;
	Out.Color = Diffuse;

#if !defined(SA_UI_SHADER_NORMAL_TYPE) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ONLY) && !defined(SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ALPHA)
	float4 vWorldPos = mul(Pos, mWorld);
	Out.Screen.x = ((vWorldPos.x + vScreenSize.x * 0.5f) + PIXEL_CORRECTION) / vScreenSize.x;
	Out.Screen.y = 1.f - ((vWorldPos.y + vScreenSize.y * 0.5f) - PIXEL_CORRECTION) / vScreenSize.y;
#endif

	return Out;
}

float4 PS( VS_OUTPUT In) : COLOR
{
#ifdef SA_UI_SHADER_NORMAL_TYPE
	return In.Color * tex2D(DecaleSamp, In.Tex);
#endif

#ifdef SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ONLY
	return tex2D(DecaleSamp, In.Tex);
#endif

#ifdef SA_UI_SHADER_NORMAL_TYPE_TEXTURE_ALPHA
	return float4(In.Color.xyz, In.Color.w * tex2D(DecaleSamp, In.Tex).w);
#endif

#ifdef SA_UI_SHADER_MULTIPLY_TYPE
	float4 fBlend = In.Color;

	fBlend *= tex2D( DecaleSamp, In.Tex );

	float4 fBase = tex2D( ScreenSamp, In.Screen);

	return float4(fBase.xyz * fBlend.xyz, fBlend.w);
#endif

#ifdef SA_UI_SHADER_ADD_TYPE
	float4 fBlend = In.Color;

	fBlend *= tex2D( DecaleSamp, In.Tex );

	float4 fBase = tex2D( ScreenSamp, In.Screen);

	return float4(min(fBase.xyz + fBlend.xyz, 1.f), fBlend.w);
#endif

#ifdef SA_UI_SHADER_SUBSTRACT_TYPE
	float4 fBlend = In.Color;

	fBlend *= tex2D( DecaleSamp, In.Tex );

	float4 fBase = tex2D( ScreenSamp, In.Screen);

	return float4(max(fBase.xyz - fBlend.xyz, 0.f), fBlend.w);
#endif

#ifdef SA_UI_SHADER_HARD_LIGHT_TYPE
	float4 fBlend = In.Color;

	fBlend *= tex2D( DecaleSamp, In.Tex );

	float4 fBase = tex2D( ScreenSamp, In.Screen);

	if(fBlend.x < 0.5f) fBlend.x = 2.f * fBase.x * fBlend.x;
	else			    fBlend.x = 1.f - 2.f * (1.f - fBlend.x) * (1.f - fBase.x);

	if(fBlend.y < 0.5f) fBlend.y = 2.f * fBase.y * fBlend.y;
	else			    fBlend.y = 1.f - 2.f * (1.f - fBlend.y) * (1.f - fBase.y);

	if(fBlend.z < 0.5f) fBlend.z = 2.f * fBase.z * fBlend.z;
	else			    fBlend.z = 1.f - 2.f * (1.f - fBlend.z) * (1.f - fBase.z);

	return fBlend;
#endif
}
technique UberShader
{
    pass P0
    {
        VertexShader = compile vs_1_1 VS();
        PixelShader  = compile ps_2_0 PS();
    }
}
