/*=============================================================================
	DOFAndBloomGatherPixelShader.usf: Pixel shader for gathering the combined depth of field and bloom samples for blurring.
	Copyright © 2006 Epic Games, Inc. All Rights Reserved.
=============================================================================*/

#include "Common.usf"

#if !XBOX || (NUM_SAMPLES != 16)

#include "DepthOfFieldCommon.usf"

/** The number of float4s the 2D sample offsets are packed into. */
#define NUM_CHUNKS ((NUM_SAMPLES + 1) / 2)

/** The amount bloomed colors are scaled by. */
half BloomScale;

/**
 * Computes the depth of field unfocused color and bloom color for a pixel.
 * @param UV - The pixel's UVs.
 * @return The combined unfocused color and bloom color, with the unfocused percent in the alpha channel.
 */
half4 ComputeWeightedSample(float2 UV)
{
	half UnfocusedPercent = CalcUnfocusedPercent(CalcSceneDepth(UV));
	half3 SceneColor = CalcSceneColor(UV);

	// The bloom color is the scaled scene color if it has a component outside the displayable range(0...1).
	// only bloom if(SceneColor>1) in order to mimic XBOX behavior due to having unsigned SceneColor values
	//half3 BloomColor = any(SceneColor < 0 || SceneColor > 1) ? (SceneColor * BloomScale) : 0;
	half3 BloomColor = any(SceneColor > 1) ? (SceneColor * BloomScale) : 0;

	// The unfocused color is the scene color scaled by the unfocused percent.
	half3 UnfocusedColor = UnfocusedPercent * SceneColor;

	return half4(
		UnfocusedColor + BloomColor,
		UnfocusedPercent
		);
}

/** The entry point. */
void Main(
	in float4 OffsetUVs[NUM_CHUNKS] : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half4 Result = 0;
	for(int ChunkIndex = 0;ChunkIndex < NUM_SAMPLES / 2;ChunkIndex++)
	{
		Result += ComputeWeightedSample(OffsetUVs[ChunkIndex].xy);
		Result += ComputeWeightedSample(OffsetUVs[ChunkIndex].wz);
	}
	if(NUM_SAMPLES / 2 < NUM_CHUNKS)
	{
		Result += ComputeWeightedSample(OffsetUVs[NUM_CHUNKS - 1].xy);		
	}
	//nse vbunny--
	#if SUPPORTS_FP_FILTERING
		OutColor = Result / NUM_SAMPLES;
	#else
		OutColor = Result / NUM_SAMPLES / 4;
	#endif
	//--nse vbunny
}

#else

half4 PackedParameters;

static half FocusDistance = PackedParameters.r;
static half InverseFocusRadius = PackedParameters.g;
static half FocusExponent = PackedParameters.b;

float2 MinMaxBlurClamp;

half BloomScale;

half4 ComputeWeightedSample( float2 UV )
{
    half DeviceZ = tex2D(SceneDepthTexture, UV).r;
    half3 SceneColor = tex2D(SceneColorTexture, UV).rgb;

    half SceneDepth = ConvertToClipSpaceW(DeviceZ);  
  
    half RelativeDistance = (SceneDepth - FocusDistance);
    
    half MaxUnfocusedPercent = (RelativeDistance < 0) ? MinMaxBlurClamp.x : MinMaxBlurClamp.y;
    half UnfocusedPercent = min(MaxUnfocusedPercent, pow(RelativeDistance * InverseFocusRadius, FocusExponent));

    half ActiveBloomScale = any(SceneColor > 1) ? BloomScale : 0;

    half3 UnfocusedColor = (UnfocusedPercent + ActiveBloomScale) * SceneColor;

	return half4( UnfocusedColor, UnfocusedPercent );
}

void Main ( in float4 OffsetUVs[8] : TEXCOORD0, out float4 OutColor : COLOR0 ) 
{
	half4 Result = 0;

	// Unrolled loop for the 16 samples.

	Result += ComputeWeightedSample(OffsetUVs[0].xy);
	Result += ComputeWeightedSample(OffsetUVs[0].wz);
									
	Result += ComputeWeightedSample(OffsetUVs[1].xy);
	Result += ComputeWeightedSample(OffsetUVs[1].wz);
									
	Result += ComputeWeightedSample(OffsetUVs[2].xy);
	Result += ComputeWeightedSample(OffsetUVs[2].wz);	
	
	Result += ComputeWeightedSample(OffsetUVs[3].xy);
	Result += ComputeWeightedSample(OffsetUVs[3].wz);	
	
	// We isolate the second section so that the HLSL compiler doesn't bias _all_ texture
	// fetches to be at the beginning of the shader.  This way the top and bottom section
	// are optimized in isolation and there will be at least two sections of tfetches.
	//
	// Note: Changing the shader in any way may require rebalancing where the isolate
	//       section should go.
	
	[isolate]
	{		
		Result += ComputeWeightedSample(OffsetUVs[4].xy);
		Result += ComputeWeightedSample(OffsetUVs[4].wz);
																   							 
		Result += ComputeWeightedSample(OffsetUVs[5].xy);
		Result += ComputeWeightedSample(OffsetUVs[5].wz);
									   
		Result += ComputeWeightedSample(OffsetUVs[6].xy);
		Result += ComputeWeightedSample(OffsetUVs[6].wz);
									 
		Result += ComputeWeightedSample(OffsetUVs[7].xy);
		Result += ComputeWeightedSample(OffsetUVs[7].wz);
	}
	
	// RETURN_COLOR not needed unless writing to SceneColor
	OutColor = Result / 16;
}

#endif
