////////////////////////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////////////////////////

#include "../../../types.txt"

////////////////////////////////////////////////////////////////////////////////////////////////////
// Structuers
////////////////////////////////////////////////////////////////////////////////////////////////////

struct PS_INPUT
{
#if MIX_SM_HIGH
	float4 pos : SV_POSITION;
#endif //MIX_SM_HIGH
	float2 tex : TEXCOORD0;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Constant values
////////////////////////////////////////////////////////////////////////////////////////////////////

static const float3 LUM_VECTOR = { 0.299, 0.587, 0.114 };

static const float  FXAA_SPAN_MAX = 8.0;
static const float  FXAA_REDUCE_MUL = 1.0 / 8.0;
static const float  FXAA_REDUCE_MIN = 1.0 / 128.0;

////////////////////////////////////////////////////////////////////////////////////////////////////
// Grobal values
////////////////////////////////////////////////////////////////////////////////////////////////////

#if MIX_SM_HIGH

	cbuffer cbInput : register( b0 )
	{
		float4 g_TexCoords0     : register( c0 );
		float4 g_TexCoords1     : register( c1 );
		float2 g_InvScreenSize  : register( c2 );
	};

	Texture2D    g_ColorTexture : register( t0 );
	SamplerState g_ColorSampler : register( s0 );
	
#else //MIX_SM_HIGH

	float4 g_TexCoords0    : register( c0 );
	float4 g_TexCoords1    : register( c1 );
	float2 g_InvScreenSize : register( c2 );

	sampler g_ColorSampler : register( s0 );

#endif //MIX_SM_HIGH

////////////////////////////////////////////////////////////////////////////////////////////////////
// }N
////////////////////////////////////////////////////////////////////////////////////////////////////

#if MIX_SM_HIGH

	#define TEX_COLOR( uv ) g_ColorTexture.Sample( g_ColorSampler, uv )

#else //MIX_SM_HIGH

	#define TEX_COLOR( uv ) tex2D( g_ColorSampler, uv )

#endif //MIX_SM_HIGH

#define TO_NW g_TexCoords0.xy //( -1.0 / W, -1.0 / H )
#define TO_NE g_TexCoords0.zw //(  1.0 / W, -1.0 / H )
#define TO_SW g_TexCoords1.xy //( -1.0 / W,  1.0 / H )
#define TO_SE g_TexCoords1.zw //(  1.0 / W,  1.0 / H )
#define INV_SCREEN_SIZE g_InvScreenSize.xy

////////////////////////////////////////////////////////////////////////////////////////////////////
// C
////////////////////////////////////////////////////////////////////////////////////////////////////

float4 main( PS_INPUT input ) : MSV_TARGET0
{
	float4 color = TEX_COLOR( input.tex );

	float3 rgbNW = TEX_COLOR( input.tex + TO_NW ).rgb;
	float3 rgbNE = TEX_COLOR( input.tex + TO_NE ).rgb;
	float3 rgbSW = TEX_COLOR( input.tex + TO_SW ).rgb;
	float3 rgbSE = TEX_COLOR( input.tex + TO_SE ).rgb;
	float3 rgbM  = color.rgb;

	float lumaNW = dot( rgbNW, LUM_VECTOR );
	float lumaNE = dot( rgbNE, LUM_VECTOR );
	float lumaSW = dot( rgbSW, LUM_VECTOR );
	float lumaSE = dot( rgbSE, LUM_VECTOR );
	float lumaM  = dot( rgbM,  LUM_VECTOR );

	float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );
	float lumaMax = max( lumaM, max( max( lumaNW, lumaNE ), max( lumaSW, lumaSE ) ) );

	float2 dir;
	float dirReduce;
	float rcpDirMin;
	float3 rgbA;
	float3 rgbB;
	float lumaB;

	float4 output;

	dir.x = -( ( lumaNW + lumaNE ) - ( lumaSW + lumaSE ) );
	dir.y =  ( ( lumaNW + lumaSW ) - ( lumaNE + lumaSE ) );

	dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );

	rcpDirMin = rcp( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );

	dir = min( float2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX ), max( float2( -FXAA_SPAN_MAX, -FXAA_SPAN_MAX ), dir * rcpDirMin ) ) * INV_SCREEN_SIZE;

	rgbA = ( 1.0 / 2.0 ) * ( TEX_COLOR( input.tex + dir * ( 1.0 / 3.0 - 0.5 ) ).rgb +
	                         TEX_COLOR( input.tex + dir * ( 2.0 / 3.0 - 0.5 ) ).rgb );

	rgbB = rgbA * ( 1.0 / 2.0 ) + ( 1.0 / 4.0 ) * ( TEX_COLOR( input.tex + dir * ( 0.0 / 3.0 - 0.5 ) ).rgb +
	                                                TEX_COLOR( input.tex + dir * ( 3.0 / 3.0 - 0.5 ) ).rgb );

	lumaB = dot( rgbB, LUM_VECTOR );

	if( ( lumaB < lumaMin ) ||
	    ( lumaB > lumaMax ) )
	{
		output = float4( rgbA, color.a );
	}
	else
	{
		output = float4( rgbB, color.a );
	}

	return output;
}
