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

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

////////////////////////////////////////////////////////////////////////////////////////////////////
// Constant
////////////////////////////////////////////////////////////////////////////////////////////////////

static const float2 LF_TEX_CENTER = float2( 0.5, 0.5 );
static const float LF_INV_HALF_LEN = 1.414213586746190517658585729081; // length( float2( 0.5, 0.5 ) )

#define MIN_GHOST 1
#define MAX_GHOST 32

////////////////////////////////////////////////////////////////////////////////////////////////////
// Structures
////////////////////////////////////////////////////////////////////////////////////////////////////

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

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

#if MIX_SM_HIGH

	cbuffer cbInput : register( b0 )
	{
		float4 g_Param0;
		float4 g_Param1;
	};

	Texture2D    g_ColorTexture : register( t0 );
	SamplerState g_ColorSampler : register( s0 );

	Texture2D    g_GhostTexture : register( t1 );
	SamplerState g_GhostSampler : register( s1 );

#else //MIX_SM_HIGH

	float4 g_Param0 : register( c0 );
	float4 g_Param1 : register( c1 );

	sampler g_ColorSampler : register( s0 );
	sampler g_GhostSampler : register( s1 );

#endif //MIX_SM_HIGH

////////////////////////////////////////////////////////////////////////////////////////////////////
// Macros
////////////////////////////////////////////////////////////////////////////////////////////////////

#if MIX_SM_HIGH
	#define TEX_COLOR( uv ) g_ColorTexture.Sample( g_ColorSampler, uv )
	#define TEX_GHOST( uv ) g_GhostTexture.Sample( g_GhostSampler, uv )
#else //MIX_SM_HIGH
	#define TEX_COLOR( uv ) tex2D( g_ColorSampler, uv )
	#define TEX_GHOST( uv ) tex2D( g_GhostSampler, uv )
#endif //MIX_SM_HIGH

#define LF_DISTO g_Param0.xyz
#define LF_GHOST_NUM_F g_Param0.w
#define LF_GHOST_WEIGHT g_Param1.x
#define LF_GHOST_DISP g_Param1.y
#define LF_HALO_WEIGHT g_Param1.z
#define LF_HALO_WIDTH g_Param1.w

////////////////////////////////////////////////////////////////////////////////////////////////////
// Sub function
////////////////////////////////////////////////////////////////////////////////////////////////////

float4 TexDistorted( float2 tex, float2 dir )
{
	float4 output;
	
	output.r = TEX_COLOR( tex + dir * LF_DISTO.r ).r;
	output.g = TEX_COLOR( tex + dir * LF_DISTO.g ).g;
	output.b = TEX_COLOR( tex + dir * LF_DISTO.b ).b;
	output.a = 1.0;

	return output;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Main function
////////////////////////////////////////////////////////////////////////////////////////////////////

static const float2 TO = float2( 0.0009765625, 0.0013020833333 );
static const float2 TO2 = TO * 2.0;

float4 main( PS_INPUT input ) : MSV_TARGET0
{
	int numGhost = clamp( ( int )LF_GHOST_NUM_F, MIN_GHOST, MAX_GHOST );

	float2 ghostTex = -input.tex + float2( 1.0, 1.0 );
	float2 ghostVec = ( LF_TEX_CENTER - ghostTex ) * LF_GHOST_DISP;
	float2 ghostDir = normalize( ghostVec );

#if ENABLE_HALO
	float2 haloVec = normalize( ghostVec ) * LF_HALO_WIDTH;
	float2 haloTex = frac( ghostTex + haloVec );
#endif //ENABLE_HALO

	float4 output = 0.0;
	
	float weight;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Ghost
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// Sampling
	[unroll(MAX_GHOST)]
	for( int i = 0; i < numGhost; i++ )
	{
		float step = ( float )i;
		float2 offset = frac( ghostTex + ghostVec * step );

		weight = length( LF_TEX_CENTER - offset ) * LF_INV_HALF_LEN;
		weight = pow( abs( 1.0 - weight ), LF_GHOST_WEIGHT );

		output += TexDistorted( offset, ghostDir ) * weight;
	}
	
#if ENABLE_GHOST_TEX
	// Coloring
	output *= TEX_GHOST( float2( length( LF_TEX_CENTER - ghostTex ) * LF_INV_HALF_LEN, LF_TEX_CENTER.y ) );
#endif //ENABLE_GHOST_TEX

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Halo
	////////////////////////////////////////////////////////////////////////////////////////////////////

#if ENABLE_HALO
	weight = length( LF_TEX_CENTER - haloTex ) * LF_INV_HALF_LEN;
	weight = pow( abs( 1.0 - weight ), LF_HALO_WEIGHT );
	output += TexDistorted( haloTex, ghostDir ) * weight;
#endif //ENABLE_HALO

	output.a = length( output.rgb );

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return output;
}
