//--------------------------------------------------------------------------------------
// Textures & Constant Buffer Variables
//--------------------------------------------------------------------------------------
Texture2D posIn :				register( t0 );
Texture2D normalIn :			register( t1 );
Texture2D depthIn :				register( t2 );
Texture3D lightVolumeRed :		register( t3 );
Texture3D lightVolumeGreen :	register( t4 );
Texture3D lightVolumeBlue :		register( t5 );

SamplerState samLinear :register( s0 );
SamplerState samPoint :	register( s1 );

cbuffer cbChangesOnRenderTarget : register( b0 )
{
    float4 lpvMiddle;
	float4 lpvGrid; // xyz Texture Dimensions; w CellSize
	float4 camData; //x: nearPlane, y: farPlane, z: foV
};

//--------------------------------------------------------------------------------------
// Static & Structs Variables
//--------------------------------------------------------------------------------------

static const float PI = 3.14159265f;

static const float band0Factor = 0.282094792f;
static const float band1Factor = 0.488602512f;

static const float indirectLightningFactor = 1.00f;

//--------------------------------------------------------------------------------------
struct VS_INPUT
{
    float2 Pos : POSITION;
    float2 Tex : TEXCOORD0;
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD0;
};

//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------

float4 calcSHIntesity( float3 direction ) {
	return float4( band0Factor, -band1Factor * direction.y, band1Factor * direction.z, -band1Factor * direction.x );
}

//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos.xy = input.Pos;
	output.Pos.zw = float2(0.0f,1.0f);
    output.Tex = input.Tex;
    
    return output;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( PS_INPUT input) : SV_TARGET
{
	float4 pos = posIn.Sample( samPoint, input.Tex ); pos.w=1.0f;
	float3 normal = normalIn.Sample( samPoint, input.Tex );
	float depth = depthIn.Sample( samPoint, input.Tex );

	float4 shIntensity = calcSHIntesity( -normal );
	float3 lpvTex = (pos.xyz - lpvMiddle.xyz) / (lpvGrid.w * 0.5f);
	lpvTex.x = (lpvTex.x + 1.0f) * 0.5f;
	lpvTex.y = (lpvTex.y - 1.0f) * -0.5f;
	lpvTex.z = (lpvTex.z + 1.0f) * 0.5f;

	float4 lpvIntensity;
	lpvIntensity.x = dot( shIntensity , lightVolumeRed.Sample( samLinear, lpvTex ) );
	lpvIntensity.y = dot( shIntensity , lightVolumeGreen.Sample( samLinear, lpvTex ) );
	lpvIntensity.z = dot( shIntensity , lightVolumeBlue.Sample( samLinear, lpvTex ) );
	lpvIntensity.w = 0.0f;

	float cellSize = lpvGrid.w / lpvGrid.x;

	int2 dim;
	posIn.GetDimensions( dim.x, dim.y );
	float2 texelSize = (camData.x + depth * camData.y) * tan(camData.z)  / ( (float)dim.xy * 0.5f);

	//return indirectLightningFactor * max( 0.0f, lpvIntensity * 4.0f / ((cellSize * cellSize) / (texelSize.x * texelSize.y)) );
	return indirectLightningFactor * max( 0.0f, lpvIntensity * 4.0f / ((texelSize.x * texelSize.y)) );
	//return indirectLightningFactor * max( 0.0f, lpvIntensity * 4.0f / (cellSize * cellSize) );
	//return indirectLightningFactor * max( 0.0f, lpvIntensity * 4.0f);
	//return float4(0.0f,0.0f,0.0f,0.0f);
}

