//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------

Texture2D hdrTex : register( t0 ); 
Texture2D lumTex : register( t1 ); 

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

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

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

struct PS_INPUT_APPLY
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD0;
	float avgLum : TEXCOORD1;
};

static const float midLum = 0.72f;
static const float lWhite = 1.5f;
static const float4 lumVector = float4(0.2126f, 0.7152f, 0.0722f, 0.0f);


//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos.xy = input.Pos;
	output.Pos.z = 0.0f;
	output.Pos.w = 1.0f;
    output.Tex = input.Tex;

    return output;
}

PS_INPUT_APPLY ApplyVS( VS_INPUT input )
{
    PS_INPUT_APPLY output = (PS_INPUT_APPLY)0;
    output.Pos.xy = input.Pos;
	output.Pos.z = 0.0f;
	output.Pos.w = 1.0f;
    output.Tex = input.Tex;

	output.avgLum = lumTex.SampleLevel( samPoint, float2(0.0f,0.0f), 0 );
    
    return output;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float FirstReducePS( PS_INPUT input) : SV_TARGET
{
	float4 f = 0.0f;
	for(int x=-1; x <= 1; x++) {
		for(int y=-1; y <= 1; y++) {
			f += dot(hdrTex.Sample( samPoint, input.Tex, int2(x,y) ),lumVector);
		}
	}
	return f/9.0f;
}

float ReducePS( PS_INPUT input) : SV_TARGET
{
	float4 f = 0.0f;
	for(int x=-1; x <= 1; x++) {
		for(int y=-1; y <= 1; y++) {
			f += lumTex.Sample( samPoint, input.Tex, int2(x,y) );
		}
	}
	return f/9.0f;
}

float4 ApplyPS( PS_INPUT_APPLY input) : SV_TARGET
{
	float4 color = hdrTex.Sample( samLinear, input.Tex );

	float pLum = dot(color,lumVector);

	float scaledLum = pLum * (midLum / (input.avgLum));
	//float scaledLum = pLum * (midLum / (1.0f));
	float finalLum = (scaledLum * ( 1.0f + scaledLum / (lWhite) ) ) / ( 1.0f + scaledLum );

	return color * finalLum;
}