/*=============================================================================
	ModShadowProjectionPixelShader.usf: Pixel shader for projecting a shadow depth buffer onto the scene.
	Copyright 1998-2007 Epic Games, Inc. All Rights Reserved.
=============================================================================*/

#include "Common.usf"
#include "ModShadowCommon.usf"
#include "ShadowProjectionCommon.usf"

float4x4 ScreenToShadowMatrix;

/**
* Entry point for uniform manual PCF that supports lights using modulative shadows.
*/
void Main(
	in float4 ScreenPosition : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half SceneW = PreviousDepth(ScreenPosition);

	float4 ShadowPosition = MulMatrix(ScreenToShadowMatrix,float4(ScreenPosition.xy / ScreenPosition.w * SceneW,SceneW,1));
	ShadowPosition.xy /= ShadowPosition.w;
	ShadowPosition.z = min(ShadowPosition.z,0.999);

	half Shadow = ManualPCF(ShadowPosition);
	
#if MODSHADOW_LIGHTTYPE_DIRECTIONAL
	// no attenuation necessary for directional lights
	half ShadowAtt = 1;
#else
	// attenuate between shadow color and white based on distance
	half ShadowAtt = ShadowAttenuation(ScreenPosition,SceneW);
#endif

	// add modulated/attenuated shadow color to shadow
	float4 ShadowedColor = lerp(float4(1,1,1,1),ShadowModulateColor,ShadowAtt);
	float4 UnshadowedColor = float4(1,1,1,1);

#if SM2_PROFILE
	// Workaround for darkened shadow frustums on x800 cards
	// Using modulative blending to ARGB8 with a src value of 1.0f darkens scene color
	clip(1.0f - Shadow - 1.0f / 255.0f);
#endif

	OutColor = lerp(ShadowedColor,UnshadowedColor,Square(Shadow));
	// RETURN_COLOR not needed with modulative blending
}


/**
* Entry point for uniform hardware PCF that supports lights using modulative shadows.
*/
void HardwarePCFMain(
	in float4 ScreenPosition : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half SceneW = PreviousDepth(ScreenPosition);

	float4 ShadowPosition = MulMatrix(ScreenToShadowMatrix,float4(ScreenPosition.xy / ScreenPosition.w * SceneW,SceneW,1));
	ShadowPosition.xy /= ShadowPosition.w;
	ShadowPosition.z = min(ShadowPosition.z,0.999);

	half Shadow = HardwarePCF(ShadowPosition);
	
#if MODSHADOW_LIGHTTYPE_DIRECTIONAL
	// no attenuation necessary for directional lights
	half ShadowAtt = 1;
#else
	// attenuate between shadow color and white based on distance
	half ShadowAtt = ShadowAttenuation(ScreenPosition,SceneW);
#endif

	// add modulated/attenuated shadow color to shadow
	float4 ShadowedColor = lerp(float4(1,1,1,1),ShadowModulateColor,ShadowAtt);
	float4 UnshadowedColor = float4(1,1,1,1);

	OutColor = lerp(ShadowedColor,UnshadowedColor,Square(Shadow));
	// RETURN_COLOR not needed with modulative blending
}

/**
* Entry point for uniform Fetch4 PCF that supports lights using modulative shadows.
*/
void Fetch4Main(
	in float4 ScreenPosition : TEXCOORD0,
	out float4 OutColor : COLOR0
	)
{
	half SceneW = PreviousDepth(ScreenPosition);

	float4 ShadowPosition = MulMatrix(ScreenToShadowMatrix,float4(ScreenPosition.xy / ScreenPosition.w * SceneW,SceneW,1));
	ShadowPosition.xy /= ShadowPosition.w;
	ShadowPosition.z = min(ShadowPosition.z,0.999);

	half Shadow = Fetch4PCF(ShadowPosition);
	
#if MODSHADOW_LIGHTTYPE_DIRECTIONAL
	// no attenuation necessary for directional lights
	half ShadowAtt = 1;
#else
	// attenuate between shadow color and white based on distance
	half ShadowAtt = ShadowAttenuation(ScreenPosition,SceneW);
#endif

	// add modulated/attenuated shadow color to shadow
	float4 ShadowedColor = lerp(float4(1,1,1,1),ShadowModulateColor,ShadowAtt);
	float4 UnshadowedColor = float4(1,1,1,1);

	OutColor = lerp(ShadowedColor,UnshadowedColor,Square(Shadow));
	// RETURN_COLOR not needed with modulative blending
}