#include "Common.hlsl"

static const int    MAX_SAMPLES = 16;    // Maximum texture grabs
static const float	FLOAT_MAX	= 9999.0f;

// The per-color weighting to be used for luminance calculations in RGB order.
static const float3 LUMINANCE_VECTOR  = float3(0.2125f, 0.7154f, 0.0721f);

sampler DownsampleSrcTexture;
float4  SampleOffsets[MAX_SAMPLES];

struct vertexShaderOutput
{
	float4	Position : POSITION;
	float2	TexCoord : TEXCOORD0;
};

vertexShaderOutput vertexShader(float4 Position : POSITION,float3 TexCoord : TEXCOORD0)
{
	vertexShaderOutput Result;
	Result.Position = Position;
	Result.TexCoord = TexCoord;
	return Result;
}


float4 Downsample4x4ColorPS(float2 UV : TEXCOORD0) : COLOR0
{
    const int NUM_SAMPLES = 16;
    float4 vColor = 0.0f;

    for( int i=0; i < NUM_SAMPLES; i++ )
    {
        vColor += tex2D( DownsampleSrcTexture, UV + SampleOffsets[i].xy );
    }
    
    RETURN_COLOR( vColor / NUM_SAMPLES );
}


float4 Downsample4x4ScalarPS(float2 UV : TEXCOORD0) : COLOR0
{
    const int NUM_SAMPLES = 16;
    float fAvgLum = 0.0f;
	float fMin = FLOAT_MAX;
	float fMax = -FLOAT_MAX;

    for( int i=0; i < NUM_SAMPLES; i++ )
    {
		float3 vSample = tex2D( DownsampleSrcTexture, UV + SampleOffsets[i].xy ).rgb;
        fAvgLum += vSample.r;
		
		fMin = min(fMin, vSample.g);
		fMax = max(fMax, vSample.b);
    }

    fAvgLum /= NUM_SAMPLES;
    return float4(fAvgLum, fMin, fMax, 1.0f);
}


float4 SampleLuminanceInitialPS(float2 UV : TEXCOORD0) : COLOR0
{	
    const int NUM_SAMPLES = 9;
    float fSum = 0.0f;
	float fMin = FLOAT_MAX;
	float fMax = -FLOAT_MAX;

    for( int i = 0; i < NUM_SAMPLES; i++ )
    {
        // Compute the sum of log(luminance) throughout the sample points
        float3 vColor     = tex2D( DownsampleSrcTexture, UV + SampleOffsets[i].xy ).rgb;
        float  fLuminance = dot( vColor, LUMINANCE_VECTOR );
		float fLogLum = log( fLuminance + 0.0001f );
        fSum += fLogLum;

		fMin = min(fMin, fLogLum);
		fMax = max(fMax, fLogLum);
    }
    
    // Divide the sum to complete the average
    fSum /= NUM_SAMPLES;

    return float4( fSum, fMin, fMax, 1.0f );
}


float4 SampleLuminanceFinalPS(float2 UV : TEXCOORD0) : COLOR0
{    
    const int NUM_SAMPLES = 16;
    float3 vResult = 0.0f;
	vResult.g = FLOAT_MAX;
	vResult.b= -FLOAT_MAX;

    for( int i = 0; i < NUM_SAMPLES; i++ )
    {
        // Compute the sum of luminance throughout the sample points
		float3 vSample = tex2D( DownsampleSrcTexture,  UV + SampleOffsets[i].xy ).rgb;
        vResult.r += vSample.r;

		vResult.g = min(vResult.g, vSample.g);
		vResult.b = max(vResult.b, vSample.b);
    }
    
    // Divide the sum to complete the average
    vResult.r /= NUM_SAMPLES;
    
    // Perform an exp() to complete the average luminance calculation
    vResult = exp( vResult );
    
    return float4( vResult, 1.0f );
}
