/*=============================================================================
	BranchingPCFProjectionPixelShader.usf: Contains pixel shaders that project a shadow depth buffer onto the scene
		using normal lighting, and then take advantage of dynamic branching to do efficient PCF.
	Copyright 1998-2010 Epic Games, Inc. All Rights Reserved.
=============================================================================*/

#include "BranchingPCFCommon.usf"

float ShadowFadeFraction;

/**
* Entry point for branching manual PCF that supports all light types that use normal shadows.
*/
void Main(
	in float4 ScreenPosition : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half SceneW;
	float4 ShadowPosition;
	CalculateShadowPosition(ScreenPosition, ShadowPosition, SceneW);
	
	half ShadowCoverage = EdgeSamplesManualPCF(ScreenPosition, ShadowPosition);
	
	//if we're not totally in shadow or totally out, then we are in the penumbra. 
	//take more samples to refine the coverage.
	if (ShadowCoverage > .0001 && ShadowCoverage < .9999) {
	
		half RefinedShadowCoverage = RefiningSamplesManualPCF(ShadowPosition);
		
		//weight the edge coverage with the refined coverage, which has to be normalized first
		ShadowCoverage = lerp(ShadowCoverage, RefinedShadowCoverage, .7);
	}

	// RETURN_COLOR not needed unless writing to SceneColor;
	// ShadowCoverage raised to the 3rd power helps the penumbra edges blend into the surrounding shadow
	OutColor = lerp(1.0f, Square(ShadowCoverage * ShadowCoverage * ShadowCoverage), ShadowFadeFraction);
}


/**
* Entry point for branching hardware PCF that supports all light types that use normal shadows.
*/
void HardwarePCFMain(
	in float4 ScreenPosition : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half SceneW;
	float4 ShadowPosition;
	CalculateShadowPosition(ScreenPosition, ShadowPosition, SceneW);

	half ShadowCoverage = EdgeSamplesHardwarePCF(ScreenPosition, ShadowPosition);

	//if we're not totally in shadow or totally out, then we are in the penumbra. 
	//take more samples to refine the coverage.
	if (ShadowCoverage > .0001 && ShadowCoverage < .9999) {
	
		half RefinedShadowCoverage = RefiningSamplesHardwarePCF(ShadowPosition);
		
		//weight the edge coverage with the refined coverage, which has to be normalized first
		ShadowCoverage = lerp(ShadowCoverage, RefinedShadowCoverage, .7);
	}

	// RETURN_COLOR not needed unless writing to SceneColor;
	// ShadowCoverage raised to the 3rd power helps the penumbra edges blend into the surrounding shadow
	OutColor = lerp(1.0f, Square(ShadowCoverage * ShadowCoverage * ShadowCoverage), ShadowFadeFraction);
}

/**
* Entry point for branching Fetch4 PCF that supports all light types that use normal shadows.
*/
void Fetch4Main(
	in float4 ScreenPosition : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half SceneW;
	float4 ShadowPosition;
	CalculateShadowPosition(ScreenPosition, ShadowPosition, SceneW);

	half ShadowCoverage = EdgeSamplesFetch4(ScreenPosition, ShadowPosition);

	//if we're not totally in shadow or totally out, then we are in the penumbra. 
	//take more samples to refine the coverage.
	if (ShadowCoverage > .0001 && ShadowCoverage < .9999) {
	
		half RefinedShadowCoverage = RefiningSamplesFetch4(ShadowPosition);
		
		//weight the edge coverage with the refined coverage
		ShadowCoverage = lerp(ShadowCoverage, RefinedShadowCoverage, .7);
	}

	// RETURN_COLOR not needed unless writing to SceneColor;
	// ShadowCoverage raised to the 3rd power helps the penumbra edges blend into the surrounding shadow
	OutColor = lerp(1.0f, Square(ShadowCoverage * ShadowCoverage * ShadowCoverage), ShadowFadeFraction);
}


