//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======//
//
//=============================================================================//
// STATIC: "DETAILTEXTURE"				"0..1"
// STATIC: "CUBEMAP"					"0..1"
// STATIC: "DIFFUSELIGHTING"			"0..1"
// STATIC: "ENVMAPMASK"					"0..1"
// STATIC: "BASEALPHAENVMAPMASK"		"0..1"
// STATIC: "SELFILLUM"					"0..1"
// STATIC: "VERTEXCOLOR"				"0..1"
// STATIC: "FLASHLIGHT"					"0..1"
// STATIC: "SELFILLUM_ENVMAPMASK_ALPHA" "0..1"
// STATIC: "DETAIL_BLEND_MODE"          "0..9"
// STATIC: "SEAMLESS_BASE"              "0..1"
// STATIC: "SEAMLESS_DETAIL"            "0..1"
// STATIC: "DISTANCEALPHA"              "0..1"
// STATIC: "DISTANCEALPHAFROMDETAIL"    "0..1"
// STATIC: "SOFT_MASK"                  "0..1"
// STATIC: "OUTLINE"                    "0..1"
// STATIC: "OUTER_GLOW"                 "0..1"
// STATIC: "FLASHLIGHTDEPTHFILTERMODE"	"0..2"	[ps20b] [PC]
// STATIC: "FLASHLIGHTDEPTHFILTERMODE"	"0..2"	[ps30]  [PC]
// STATIC: "FLASHLIGHTDEPTHFILTERMODE"	"0..0"	[ps20b] [XBOX]
// STATIC: "DEPTHBLEND"					"0..1"	[ps20b] [ps30]
// STATIC: "BLENDTINTBYBASEALPHA"       "0..1"
// STATIC: "SRGB_INPUT_ADAPTER"			"0..1"	[ps20b]
// STATIC: "CUBEMAP_SPHERE_LEGACY"		"0..1"

// DYNAMIC: "PIXELFOGTYPE"				"0..1"  [ps20]
// DYNAMIC: "LIGHTING_PREVIEW"          "0..2"	[PC]
// DYNAMIC: "LIGHTING_PREVIEW"          "0..0"	[XBOX]
// DYNAMIC: "FLASHLIGHTSHADOWS"			"0..1"	[ps20b]
// DYNAMIC: "FLASHLIGHTSHADOWS"			"0..1"	[ps30]
// DYNAMIC: "STATIC_LIGHT_LIGHTMAP"	    "0..1"  [ps20b] [ps30]
// DYNAMIC: "STATIC_LIGHT_LIGHTMAP"	    "0..0"  [ps20]
// DYNAMIC: "DEBUG_LUXELS"				"0..1"	[ps20b] [ps30]

// detail blend mode 6 = ps20b only
// SKIP: $DETAIL_BLEND_MODE == 6				[ps20]

// SKIP: ($DETAILTEXTURE == 0 ) && ( $DETAIL_BLEND_MODE != 0 )
// SKIP: ($DETAILTEXTURE == 0 ) && ( $SEAMLESS_DETAIL )
// SKIP: ($ENVMAPMASK || $SELFILLUM_ENVMAPMASK_ALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL)
// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK
// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM
// SKIP: $SELFILLUM && $SELFILLUM_ENVMAPMASK_ALPHA
// SKIP: $SELFILLUM_ENVMAPMASK_ALPHA && (! $ENVMAPMASK)
// SKIP: $ENVMAPMASK && ($FLASHLIGHT || $FLASHLIGHTSHADOWS) [PC]
// SKIP: $BASEALPHAENVMAPMASK && ($SEAMLESS_BASE || $SEAMLESS_DETAIL)
// SKIP: ($DISTANCEALPHA == 0) && ($DISTANCEALPHAFROMDETAIL || $SOFT_MASK || $OUTLINE || $OUTER_GLOW)
// SKIP: ($DETAILTEXTURE == 0) && ($DISTANCEALPHAFROMDETAIL)

// We don't care about flashlight depth unless the flashlight is on
// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 )	[ps20b]
// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 )	[ps30]

// Flashlight shadow filter mode is irrelevant if there is no flashlight
// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b]
// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30]

// DISTANCEALPHA-related skips
// SKIP: ($DISTANCEALPHA) && ($ENVMAPMASK || $BASEALPHAENVMAPMASK || $SELFILLUM || $SELFILLUM_ENVMAPMASK_ALPHA )
// SKIP: ($DISTANCEALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL || $CUBEMAP || $LIGHTING_PREVIEW )
// SKIP: ($DISTANCEALPHA) && ($WRITEWATERFOGTODESTALPHA || $PIXELFOGTYPE || $FLASHLIGHT || $FLASHLIGHTSHADOWS || $SRGB_INPUT_ADAPTER )

// SKIP: $SEAMLESS_BASE && $SRGB_INPUT_ADAPTER
// SKIP: $SEAMLESS_BASE && ($BLENDTINTBYBASEALPHA )

// BlendTintByBaseAlpha is incompatible with other interpretations of alpha
// SKIP: ($BLENDTINTBYBASEALPHA) && ($SELFILLUM || (($DISTANCEALPHA) && ($DISTANCEALPHAFROMDETAIL == 0)) || $BASEALPHAENVMAPMASK)

// Only _XBOX allows flashlight and cubemap in the current implementation
// SKIP: $FLASHLIGHT && $CUBEMAP [PC]

// SKIP: $CUBEMAP_SPHERE_LEGACY && ($CUBEMAP == 0)

// Debugging luxels only makes sense if we have lightmaps on this geometry.
// SKIP: ($STATIC_LIGHT_LIGHTMAP == 0) && ($DEBUG_LUXELS == 1)

#include "common_flashlight_fxc.h"
#include "common_vertexlitgeneric_dx9.h"
 
const float4 g_EnvmapTint_TintReplaceFactor		: register( c0 );
const float4 g_DiffuseModulation				: register( c1 );
const float4 g_EnvmapContrast_ShadowTweaks		: register( c2 );
const float4 g_EnvmapSaturation_SelfIllumMask	: register( c3 );
const float4 g_SelfIllumTint_and_BlendFactor	: register( c4 );

const float4 g_ShaderControls					: register( c12 );
const float4 g_DepthFeatheringConstants			: register( c13 );

const float4 g_EyePos							: register( c20 );
const float4 g_FogParams						: register( c21 );

#define g_SelfIllumTint				g_SelfIllumTint_and_BlendFactor.xyz
#define g_DetailBlendFactor			g_SelfIllumTint_and_BlendFactor.w
#define g_EnvmapSaturation			g_EnvmapSaturation_SelfIllumMask.xyz
#define g_SelfIllumMaskControl		g_EnvmapSaturation_SelfIllumMask.w

const float4 g_FlashlightAttenuationFactors	    : register( c22 );
const HALF3 g_FlashlightPos						: register( c23 );
const float4x4 g_FlashlightWorldToTexture		: register( c24 ); // through c27


sampler BaseTextureSampler		: register( s0 );
sampler EnvmapSampler			: register( s1 );
sampler DetailSampler			: register( s2 );
sampler EnvmapMaskSampler		: register( s4 );
sampler RandRotSampler			: register( s6 );	// RandomRotation sampler
sampler FlashlightSampler		: register( s7 );
sampler ShadowDepthSampler		: register( s8 );	// Flashlight shadow depth map sampler
sampler DepthSampler			: register( s10 );	//depth buffer sampler for depth blending
sampler SelfIllumMaskSampler	: register( s11 );	// selfillummask
sampler LightMapSampler			: register( s12 );

struct PS_INPUT
{
#if SEAMLESS_BASE
	HALF3 baseTexCoord				: TEXCOORD0;	// Base texture coordinate
#else
	HALF2 baseTexCoord				: TEXCOORD0;	// Base texture coordinate
#endif
#if SEAMLESS_DETAIL
	HALF3 detailTexCoord			: TEXCOORD1;	// Seamless texture coordinate
#else
	HALF2 detailTexCoord			: TEXCOORD1;	// Detail texture coordinate
#endif
	float4 color					: TEXCOORD2;	// Vertex color (from lighting or unlit)
	float3 worldVertToEyeVector		: TEXCOORD3;	// Necessary for reflection
	float3 worldSpaceNormal			: TEXCOORD4;	// Necessary for cubemaps and flashlight

#if defined ( _X360 )
#if FLASHLIGHT
	float4 flashlightSpacePos		: TEXCOORD5;
#endif
#endif

	float4 projPos					: TEXCOORD6;
	float4 worldPos_projPosZ		: TEXCOORD7;
	float4 fogFactorW				: COLOR1;
#if SEAMLESS_BASE || SEAMLESS_DETAIL
	float3 SeamlessWeights          : COLOR0;				// x y z projection weights
#endif
};

const float4 g_GlowParameters : register( c5 );
const float4 g_GlowColor : register( c6 );
#define GLOW_UV_OFFSET g_GlowParameters.xy
#define OUTER_GLOW_MIN_DVALUE g_GlowParameters.z
#define OUTER_GLOW_MAX_DVALUE g_GlowParameters.w
#define OUTER_GLOW_COLOR g_GlowColor

#define g_fPixelFogType					g_ShaderControls.x
#define g_fWriteDepthToAlpha			g_ShaderControls.y
#define g_fWriteWaterFogToDestAlpha		g_ShaderControls.z
#define g_fVertexAlpha					g_ShaderControls.w


const float4 g_DistanceAlphaParams : register( c7 );
#define SOFT_MASK_MAX g_DistanceAlphaParams.x
#define SOFT_MASK_MIN g_DistanceAlphaParams.y

const float4 g_OutlineColor : register( c8 );
#define OUTLINE_COLOR g_OutlineColor

const float4 g_OutlineParams : register( c9 );
// these are ordered this way for optimal ps20 swizzling
#define OUTLINE_MIN_VALUE0 g_OutlineParams.x
#define OUTLINE_MAX_VALUE1 g_OutlineParams.y
#define OUTLINE_MAX_VALUE0 g_OutlineParams.z
#define OUTLINE_MIN_VALUE1 g_OutlineParams.w

#if DETAILTEXTURE
const float3 g_DetailTint : register( c10 );
#endif

#if DEBUG_LUXELS
const float4 g_LuxelScale : register( c11 );
#endif


// Calculate unified fog
float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )
{
	float flDepthBelowWater = fPixelFogType*fogParams.y - flWorldPosZ;  // above water = negative, below water = positive
	float flDepthBelowEye = fPixelFogType*flEyePosZ - flWorldPosZ;		// above eye = negative, below eye = positive
	// if fPixelFogType == 0, then flDepthBelowWater == flDepthBelowEye and frac will be 1
	float frac = (flDepthBelowEye == 0) ? 1 : saturate(flDepthBelowWater/flDepthBelowEye);
	return saturate( min(fogParams.z, flProjPosZ * fogParams.w * frac - fogParams.x) );
}

// Blend both types of Fog and lerp to get result
float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType )
{
	//float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
	//float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );
	//return lerp( fRangeResult, fHeightResult, fPixelFogType );
	pixelFogFactor = lerp( pixelFogFactor*pixelFogFactor, pixelFogFactor, fPixelFogType );
	return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor );
}


float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE, float fWriteDepthToDestAlpha, const float flProjZ )
{
	float4 result = vShaderColor;
	if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
	{
		result.rgb *= LINEAR_LIGHT_SCALE;
	}
	else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
	{
		result.rgb *= GAMMA_LIGHT_SCALE;
	}

	result.a = lerp( result.a, DepthToDestAlpha( flProjZ ), fWriteDepthToDestAlpha );

	result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType );
	result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion

	return result;
}


#if LIGHTING_PREVIEW == 2
LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR
#else
float4 main( PS_INPUT i ) : COLOR
#endif
{
	bool bDetailTexture = DETAILTEXTURE ? true : false;
	bool bCubemap = CUBEMAP ? true : false;
	bool bDiffuseLighting = DIFFUSELIGHTING ? true : false;
	bool bHasNormal = bCubemap || bDiffuseLighting;
	bool bEnvmapMask = ENVMAPMASK ? true : false;
	bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false;
	bool bSelfIllum = SELFILLUM ? true : false;
	bool bVertexColor = VERTEXCOLOR ? true : false;
	bool bFlashlight = FLASHLIGHT ? true : false;
	bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false;

	HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f );
#if SEAMLESS_BASE
	baseColor =
		i.SeamlessWeights.x * tex2D( BaseTextureSampler, i.baseTexCoord.yz )+
		i.SeamlessWeights.y * tex2D( BaseTextureSampler, i.baseTexCoord.zx )+
		i.SeamlessWeights.z * tex2D( BaseTextureSampler, i.baseTexCoord.xy );
#else
	baseColor = tex2D( BaseTextureSampler, i.baseTexCoord.xy );

#if SRGB_INPUT_ADAPTER
	baseColor.rgb = GammaToLinear( baseColor.rgb );
#endif

#endif // !SEAMLESS_BASE


#if DISTANCEALPHA && (DISTANCEALPHAFROMDETAIL == 0)
	float distAlphaMask = baseColor.a;
#endif


#if DETAILTEXTURE
#if SEAMLESS_DETAIL
	float4 detailColor = 
			i.SeamlessWeights.x * tex2D( DetailSampler, i.detailTexCoord.yz )+
			i.SeamlessWeights.y * tex2D( DetailSampler, i.detailTexCoord.zx )+
			i.SeamlessWeights.z * tex2D( DetailSampler, i.detailTexCoord.xy );
#else
	float4 detailColor = tex2D( DetailSampler, i.detailTexCoord.xy );
#endif
	detailColor.rgb *= g_DetailTint;

#if DISTANCEALPHA && (DISTANCEALPHAFROMDETAIL == 1)
	float distAlphaMask = detailColor.a;
	detailColor.a = 1.0;									// make tcombine treat as 1.0
#endif
	baseColor = 
		TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor );
#endif

#if DISTANCEALPHA
	// now, do all distance alpha effects
	//if ( OUTLINE && ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) )
	//{
	//	float oFactor=1.0;
	//	if ( distAlphaMask <= OUTLINE_MIN_VALUE1 )
	//	{
	//		oFactor=smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask );
	//	}
	//	else
	//	{
	//		oFactor=smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask );
	//	}
	//	baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor );
	//}
	if ( OUTLINE )
	{
		float4 oFactors = smoothstep(g_OutlineParams.xyzw, g_OutlineParams.wzyx, distAlphaMask );
		baseColor = lerp( baseColor, g_OutlineColor, oFactors.x * oFactors.y );
	}

	float mskUsed;
	if ( SOFT_MASK )
	{
		mskUsed = smoothstep( SOFT_MASK_MIN, SOFT_MASK_MAX, distAlphaMask );
		baseColor.a *= mskUsed;
	}
	else
	{
		mskUsed = distAlphaMask >= 0.5;
		if (DETAILTEXTURE )
			baseColor.a *= mskUsed;
		else
			baseColor.a = mskUsed;
	}
	

	if ( OUTER_GLOW )
	{
#if DISTANCEALPHAFROMDETAIL
		float4 glowTexel = 	tex2D( DetailSampler, i.detailTexCoord.xy+GLOW_UV_OFFSET );
#else
		float4 glowTexel = 	tex2D( BaseTextureSampler, i.baseTexCoord.xy+GLOW_UV_OFFSET );
#endif
		float4 glowc = OUTER_GLOW_COLOR*smoothstep( OUTER_GLOW_MIN_DVALUE, OUTER_GLOW_MAX_DVALUE, glowTexel.a );
		baseColor = lerp( glowc, baseColor, mskUsed );
	}

#endif  // DISTANCEALPHA

	float3 specularFactor = 1.0f;
	float4 envmapMaskTexel;
	if( bEnvmapMask )
	{
		envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord.xy );
		specularFactor *= envmapMaskTexel.xyz;	
	}

	if( bBaseAlphaEnvmapMask )
	{
		specularFactor *= 1.0 - baseColor.a; // this blows!
	}

	float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f );
	if( bDiffuseLighting || bVertexColor )
	{
		diffuseLighting = i.color.rgb;
	}

#if STATIC_LIGHT_LIGHTMAP
	// This matches the behavior of vertex lighting, which multiplies by cOverbright (which is not accessible here)
	// And converts from Gamma space to Linear space before being used.
	float2 lightmapTexCoords = i.baseTexCoord.xy;
	#if DEBUG_LUXELS
		lightmapTexCoords.xy *= g_LuxelScale.xy;
	#endif
	float3 f3LightmapColor = GammaToLinear( 2.0f * tex2D( LightMapSampler, lightmapTexCoords ).rgb );
	diffuseLighting = f3LightmapColor;
#endif

	float3 albedo = baseColor;

	if (bBlendTintByBaseAlpha)
	{
		float3 tintedColor = albedo * g_DiffuseModulation.rgb;
		tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_EnvmapTint_TintReplaceFactor.w);
		albedo = lerp(albedo, tintedColor, baseColor.a);
	}
	else
	{
		albedo = albedo * g_DiffuseModulation.rgb;
	}

	float alpha = g_DiffuseModulation.a;
	if ( !bBaseAlphaEnvmapMask && !bSelfIllum && !bBlendTintByBaseAlpha )
	{
		alpha *= baseColor.a;
	}


	if( bFlashlight )
	{
		int nShadowSampleLevel = 0;
		bool bDoShadows = false;
// On ps_2_b, we can do shadow mapping
#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) )
		nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE;
		bDoShadows = true;
#endif

#if defined ( _X360 )
		float4 flashlightSpacePosition = i.flashlightSpacePos;
#else
		float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture );
#endif

	// We want the N.L to happen on the flashlight pass, but can't afford it on ps20
	bool bUseWorldNormal = true;
#if ( defined( SHADER_MODEL_PS_2_0 ) && ( DETAILTEXTURE ) )
	bUseWorldNormal = false;
#endif
		float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition,
			i.worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, 
			g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler,
			RandRotSampler, nShadowSampleLevel, bDoShadows, false, i.projPos.xy / i.projPos.w, false, g_EnvmapContrast_ShadowTweaks, bUseWorldNormal );

#if defined ( _X360 )
		diffuseLighting += flashlightColor;
#else
		diffuseLighting = flashlightColor;
#endif
	}

	if( bVertexColor && bDiffuseLighting )
	{
		albedo *= i.color.rgb;
	}

	alpha = lerp( alpha, alpha * i.color.a, g_fVertexAlpha );

	float3 diffuseComponent = albedo * diffuseLighting;

#if DETAILTEXTURE
	diffuseComponent = 
		TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor );
#endif

	HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f );

#if !FLASHLIGHT || defined ( _X360 )
	#if SELFILLUM_ENVMAPMASK_ALPHA
		// range of alpha:
	    // 0 - 0.125 = lerp(diffuse,selfillum,alpha*8)
	    // 0.125-1.0 = selfillum*(1+alpha-0.125)*8 (over bright glows)
		HALF3 selfIllumComponent = g_SelfIllumTint * albedo;
		half Adj_Alpha=8*envmapMaskTexel.a;
		diffuseComponent=( max( 0, 1-Adj_Alpha ) * diffuseComponent) + Adj_Alpha * selfIllumComponent;
	#else
		if ( bSelfIllum )
		{
			float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord.xy );
			vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl );
			diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint * albedo, vSelfIllumMask );
		}
	#endif

	if( bCubemap )
	{
#if CUBEMAP_SPHERE_LEGACY
		HALF3 reflectVect = normalize(CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector.xyz ));

		specularLighting = 0.5 * tex2D( EnvmapSampler, float2(reflectVect.x, reflectVect.y) ) * g_DiffuseModulation.rgb * diffuseLighting;
#else
		HALF3 reflectVect = CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector.xyz );

		specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect );
		specularLighting *= specularFactor;
		specularLighting *= g_EnvmapTint_TintReplaceFactor.rgb;
		HALF3 specularLightingSquared = specularLighting * specularLighting;
		specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks );
		HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) );
		specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation );
#endif
	}
#endif

	HALF3 result = diffuseComponent + specularLighting;

#if LIGHTING_PREVIEW
# if LIGHTING_PREVIEW == 1
	float dotprod=0.7+0.25*dot(i.worldSpaceNormal,normalize(float3(1,2,-.5)));
	return FinalOutput( float4( dotprod*albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR );
# else
	LPREVIEW_PS_OUT ret;
	ret.flags=float4(1,1,1,1);
	ret.color=float4( albedo.xyz, alpha );
	ret.normal=float4(i.worldSpaceNormal,alpha);
	ret.position=float4(i.worldPos_projPosZ.xyz, alpha);
	return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE );
# endif
#else

#	if (DEPTHBLEND == 1)
	{
		float2 vScreenPos;
		vScreenPos.x = i.projPos.x;
		vScreenPos.y = -i.projPos.y;
		vScreenPos = (vScreenPos + i.projPos.w) * 0.5f;	
		alpha *= DepthFeathering( DepthSampler, vScreenPos / i.projPos.w, i.projPos.w - i.projPos.z, i.projPos.w, g_DepthFeatheringConstants );
	}
#	endif

#if defined( SHADER_MODEL_PS_2_0 )
	float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.projPos.z );
	#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT)
		alpha = lerp( alpha, fogFactor, g_fWriteWaterFogToDestAlpha );
	#endif
	return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.projPos.z );
#else // 2b or higher
	float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.projPos.z );
	alpha = lerp( alpha, fogFactor, g_fWriteWaterFogToDestAlpha ); // Use the fog factor if it's height fog
	return FinalOutputConst( float4( result.rgb, alpha ), fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.projPos.z );
#endif

#endif
}