//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
// Example pixel shader that can be applied to models
//
//==================================================================================================

// STATIC: "CONVERT_TO_SRGB"			"0..0"
// STATIC: "FLASHLIGHT"					"0..1"
// STATIC: "FLASHLIGHTDEPTHFILTERMODE"	"0..2"	[ps20b]

// DYNAMIC: "WRITEWATERFOGTODESTALPHA"  "0..1"
// DYNAMIC: "PIXELFOGTYPE"				"0..1"
// DYNAMIC: "NUM_LIGHTS"				"0..4"
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA"	"0..1"	[ps20b]
// DYNAMIC: "FLASHLIGHTSHADOWS"			"0..1"	[ps20b]

// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0)

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

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

#include "common_flashlight_fxc.h"
#include "shader_constant_register_map.h"

const float4 g_DiffuseModulation			: register( PSREG_DIFFUSE_MODULATION );
const float4 g_ShadowTweaks					: register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS );
const float3 cAmbientCube[6]				: register( PSREG_AMBIENT_CUBE );
const float4 g_EyePos						: register( PSREG_EYEPOS_SPEC_EXPONENT );
const float4 g_FogParams					: register( PSREG_FOG_PARAMS );
const float4 g_FlashlightAttenuationFactors	: register( PSREG_FLASHLIGHT_ATTENUATION );			// On non-flashlight pass
const float4 g_FlashlightPos_RimBoost		: register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST );
const float4x4 g_FlashlightWorldToTexture	: register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE );
PixelShaderLightInfo cLightInfo[3]			: register( PSREG_LIGHT_INFO_ARRAY );				// 2 registers each - 6 registers total (4th light spread across w's)

#define g_FlashlightPos					g_FlashlightPos_RimBoost.xyz

sampler BaseTextureSampler		: register( s0 );	// Base map, selfillum in alpha
sampler ShadowDepthSampler		: register( s4 );	// Flashlight shadow depth map sampler
sampler NormalizeRandRotSampler	: register( s5 );	// Normalization / RandomRotation samplers
sampler FlashlightSampler		: register( s6 );	// Flashlight cookie

struct PS_INPUT
{
	float2 baseTexCoord	: TEXCOORD0;
	float4 lightAtten	: TEXCOORD1;
	float3 worldNormal	: TEXCOORD2;
	float3 worldPos		: TEXCOORD3;
	float3 projPos		: TEXCOORD4;
};

float4 main( PS_INPUT i ) : COLOR
{
	float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord );

	float3 diffuseLighting;
	if ( FLASHLIGHT != 0 )
	{
		float4 flashlightSpacePosition = mul( float4( i.worldPos, 1.0f ), g_FlashlightWorldToTexture );

		diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos, flashlightSpacePosition,
			i.worldNormal, g_FlashlightAttenuationFactors.xyz, 
			g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler,
			NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, i.projPos, false, g_ShadowTweaks );
	}
	else // non-flashlight path
	{
		// Summation of diffuse illumination from all local lights
		diffuseLighting = PixelShaderDoLighting( i.worldPos, i.worldNormal,
			float3( 0.0f, 0.0f, 0.0f ), false, true, i.lightAtten,
			cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, true,

			// These are dummy parameters:
			false, 1.0f,
			false, BaseTextureSampler );
	}

	float3 result = baseColor.rgb * g_DiffuseModulation.rgb * diffuseLighting;
	float alpha = g_DiffuseModulation.a * baseColor.a;

	float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z );

#if WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
	alpha = fogFactor;
#endif

	bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 );

	return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.projPos.z );
}