/*=============================================================================
	UnlitTranslucency.hlsl: Shader for rendering unlit translucency
	Copyright © 2004-2005 Epic Games, Inc. All Rights Reserved.
=============================================================================*/

#include "Common.hlsl"
#include "UserShader.hlsl"
#include "VertexFactory.hlsl"

struct pixelShaderInput
{
	vertexFactoryInterpolants	FactoryInterpolants;
	half4						Fog				: TEXCOORD5;
	float4						ScreenPosition	: TEXCOORD6;
	float3						CameraVector	: TEXCOORD7;
};

/** closest distortion depths */
sampler DistortionDepthTexture;

float4 pixelShader(pixelShaderInput Input) : COLOR0
{
	userShaderInput	UserShaderInput = getUserShaderInputs(Input.FactoryInterpolants);
	calcUserVectors(UserShaderInput,Input.CameraVector.xyz,Input.ScreenPosition);
		
	half	Opacity = userOpacity(UserShaderInput);	

#if SHADERBLENDING_TRANSLUCENT
	RETURN_COLOR( float4(userEmissive(UserShaderInput) * Input.Fog.a + Input.Fog.rgb,Opacity) );
#elif SHADERBLENDING_ADDITIVE
	RETURN_COLOR( float4(userEmissive(UserShaderInput) * Input.Fog.a,Opacity) );
#elif SHADERBLENDING_MODULATE
	RETURN_COLOR( float4(userEmissive(UserShaderInput) * Input.Fog.a,Opacity) );
#else
	RETURN_COLOR( 0 );
#endif
}

struct vertexShaderOutput
{
	float4						Position		: POSITION;
	vertexFactoryInterpolants	FactoryInterpolants;
	half4						Fog				: TEXCOORD5;
	float4						ScreenPosition	: TEXCOORD6;
	float3						CameraVector	: TEXCOORD7;
};

float4x4	ViewProjectionMatrix;
float4		CameraPosition;

static const float FLT_EPSILON = 0.001f;

//PGMOD_BEGIN(IanW)
/** calculate ratio of distance between world z height and relative fog height */
float4 LinePlaneIntersection(float3 RelativeB,float4 RelativeZ)
{
	return RelativeZ / (abs(RelativeB.z) <= FLT_EPSILON ? FLT_EPSILON : RelativeB.z);
}

float4	FogMinHeight;
float4	FogMaxHeight;
const half3	FogInScattering[4];
const half4	FogStartDistance;
const half4	FogEndDistance;
const half4	FogStartDensity;
const half4	FogEndDensity;
//PGMOD_END(IanW)

vertexShaderOutput vertexShader(vertexInput Input)
{
	vertexShaderOutput	Result;

	float4	WorldPosition = vertexFactoryGetWorldPosition(Input,Result.FactoryInterpolants);

	//PGMOD_BEGIN(IanW)
	float3	WorldVector = WorldPosition.xyz - CameraPosition.xyz;
	float	Distance = length(WorldVector);

			// maxfog - camera / z height
	float4	MinHeightPercent = LinePlaneIntersection(WorldVector,FogMinHeight - CameraPosition.z),
			// minfog - camera / z height
			MaxHeightPercent = LinePlaneIntersection(WorldVector,FogMaxHeight - CameraPosition.z);
			// fog layer distance based on % over max/min fog heights
	half4	LayerDistance = max(half4(0,0,0,0),half4(Distance,Distance,Distance,Distance)) * abs(saturate(MaxHeightPercent) - saturate(MinHeightPercent));
			// Interpolate the scattering
	half4	FogRange = FogEndDistance - FogStartDistance;
	half4	LerpFactor = (LayerDistance - FogStartDistance) / FogRange;
	half4	Scattering = LayerDistance < FogStartDistance ? lerp(half4(1,1,1,1), FogStartDensity, LayerDistance/FogStartDistance) : (LayerDistance < FogEndDistance ? lerp(FogStartDensity, FogEndDensity, LerpFactor) : FogEndDensity);
	half4	InScattering = Scattering - 1;
	//PGMOD_END(IanW)

	Result.Fog.rgb = 0;
	Result.Fog.a = 1;

	for(int LayerIndex = 0;LayerIndex < 4;LayerIndex++)
	{
		Result.Fog *= Scattering[LayerIndex];
		Result.Fog.rgb += InScattering[LayerIndex] * FogInScattering[LayerIndex];
	}

	Result.ScreenPosition = Result.Position = mul(ViewProjectionMatrix,WorldPosition);
	Result.CameraVector = vertexFactoryWorldToTangentSpace(Input,CameraPosition.xyz - WorldPosition.xyz * CameraPosition.w);

	return Result;
}
