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

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

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

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

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

#if NUM_SAMPLES
	static const float INV_NUM_SAMPLES = 1.0 / NUM_SAMPLES;
#endif //#if NUM_SAMPLES

#define ALPHA_ENABLED 1
#define DEPTH_ENABLED 1

////////////////////////////////////////////////////////////////////////////////////////////////////
// Global values
////////////////////////////////////////////////////////////////////////////////////////////////////

#if MIX_SM_HIGH

	cbuffer cbInput : register( b0 )
	{
		float4 g_Params0;
		float4 g_Params1;
		float4 g_Params2;
	};

	Texture2D g_ColorTexture : register( t0 );
	Texture2D g_DepthTexture : register( t1 );
	Texture2D g_DataTexture  : register( t2 );

	SamplerState g_ColorSampler : register( s0 );
	SamplerState g_DepthSampler : register( s1 );
	SamplerState g_DataSampler  : register( s2 );
	
#else //MIX_SM_HIGH

	float4 g_Params0 : register( c0 );
	float4 g_Params1 : register( c1 );
	float4 g_Params2 : register( c2 );

	sampler g_ColorSampler : register( s0 );
	sampler g_DepthSampler : register( s1 );
	sampler g_DataSampler  : register( s2 );

#endif //MIX_SM_HIGH

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

#if MIX_SM_HIGH

	#define TEX_COLOR( uv ) g_ColorTexture.Sample( g_ColorSampler, uv )
	#define TEX_DEPTH( uv ) g_DepthTexture.Sample( g_DepthSampler, uv )
	#define TEX_DATA( uv ) g_DataTexture.Sample( g_DataSampler, uv )

#else //MIX_SM_HIGH

	#define TEX_COLOR( uv ) tex2D( g_ColorSampler, uv )
	#define TEX_DEPTH( uv ) tex2D( g_DepthSampler, uv )
	#define TEX_DATA( uv ) tex2D( g_DataSampler, uv )

#endif //MIX_SM_HIGH

// Addtive sampling
#define GR_LIGHTPOS g_Params0.xy
#define GR_EDOTL g_Params0.z
#define GR_DENSITY g_Params1.x
#define GR_DECAY g_Params1.y
#define GR_EXPOSURE g_Params1.z
#define GR_FI_START g_Params2.x
#define GR_FI_END g_Params2.y
#define GR_FI_INV_DIST g_Params2.z

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

float4 main( PS_INPUT input ) : MSV_TARGET0
{
#if DEPTH_ENABLED
	float intensity;
#endif //DEPTH_ENABLED

	float2 ray;
	float2 tex;
	float3 color;
	float weight;
	float3 sample;
	
	float4 output;

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

#if ALPHA_ENABLED
	clip( TEX_DATA( input.tex ).a - 0.00001 );
#endif //ALPHA_ENABLED

#if DEPTH_ENABLED
	intensity = TEX_DEPTH( input.tex ).r;
	clip( intensity - GR_FI_START );

	if( GR_FI_END > intensity )
	{
		intensity = ( intensity - GR_FI_START ) * GR_FI_INV_DIST;
	}
	else
	{
		intensity = 1.0;
	}
#endif //DEPTH_ENABLED

	ray = input.tex - GR_LIGHTPOS;
	ray *= INV_NUM_SAMPLES * GR_DENSITY;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	tex = input.tex;
	color = TEX_COLOR( tex ).rgb;
	weight = 1.0;

	for( int i = 0; i < NUM_SAMPLES; i++ )
	{
		tex -= ray;

		color += TEX_COLOR( tex ).rgb * weight;

		weight *= GR_DECAY;
	}

#if DEPTH_ENABLED
	color *= intensity;
#endif //DEPTH_ENABLED

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

	output.rgb = color * GR_EDOTL * GR_EXPOSURE;
	output.a = 1.0;

	return output;
}
