//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ======
// $SHADER_SPECIFIC_CONST_0	 = eyeball origin			
// $SHADER_SPECIFIC_CONST_1	 = eyeball up * 0.5			
// $SHADER_SPECIFIC_CONST_2	 = iris projection U		
// $SHADER_SPECIFIC_CONST_3	 = iris projection V		
// $SHADER_SPECIFIC_CONST_4	 = glint projection U		
// $SHADER_SPECIFIC_CONST_5	 = glint projection V		
//=============================================================================

//	STATIC: "INTRO"						"0..1"
//  STATIC: "HALFLAMBERT"				"0..1"
//  STATIC: "USE_STATIC_CONTROL_FLOW"	"0..1" [vs20]

//	DYNAMIC: "COMPRESSED_VERTS"			"0..1"
//	DYNAMIC: "SKINNING"					"0..1"
//	DYNAMIC: "DOWATERFOG"				"0..1"
//	DYNAMIC: "DYNAMIC_LIGHT"			"0..1"
//	DYNAMIC: "STATIC_LIGHT"				"0..1"
//  DYNAMIC: "MORPHING"					"0..1" [vs30]
//  DYNAMIC: "NUM_LIGHTS"				"0..2" [vs20]

// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo
//  SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20]

#include "vortwarp_vs20_helper.h"

static const int  g_bSkinning		= SKINNING ? true : false;
static const int  g_FogType			= DOWATERFOG;
static const bool g_bHalfLambert	= HALFLAMBERT ? true : false;

const float3 cEyeOrigin						:  register( SHADER_SPECIFIC_CONST_0 );
const float3 cHalfEyeballUp					:  register( SHADER_SPECIFIC_CONST_1 );
const float4 cIrisProjectionU				:  register( SHADER_SPECIFIC_CONST_2 );
const float4 cIrisProjectionV				:  register( SHADER_SPECIFIC_CONST_3 );
const float4 cGlintProjectionU				:  register( SHADER_SPECIFIC_CONST_4 );
const float4 cGlintProjectionV				:  register( SHADER_SPECIFIC_CONST_5 );
#if INTRO
const float4 const4							:  register( SHADER_SPECIFIC_CONST_6 );
#define g_Time const4.w
#define modelOrigin const4.xyz
#endif

#ifdef SHADER_MODEL_VS_3_0
// NOTE: cMorphTargetTextureDim.xy = target dimensions,
//		 cMorphTargetTextureDim.z = 4tuples/morph
const float3 cMorphTargetTextureDim			: register( SHADER_SPECIFIC_CONST_7 );
const float4 cMorphSubrect					: register( SHADER_SPECIFIC_CONST_8 );

sampler2D morphSampler						: register( D3DVERTEXTEXTURESAMPLER0, s0 );
#endif

struct VS_INPUT
{
	float4 vPos					: POSITION;			// Position
	float4 vBoneWeights			: BLENDWEIGHT;		// Skin weights
	float4 vBoneIndices			: BLENDINDICES;		// Skin indices
	float4 vTexCoord0			: TEXCOORD0;		// Base (sclera) texture coordinates

	float3 vPosFlex				: POSITION1;		// Delta positions for flexing
#ifdef SHADER_MODEL_VS_3_0
	float vVertexID				: POSITION2;
#endif
};

struct VS_OUTPUT
{
    float4 projPos				: POSITION;			// Projection-space position
#if !defined( _X360 )
	float  fog					: FOG;				// Fixed-function fog factor
#endif
	float2 baseTC				: TEXCOORD0;		// Base texture coordinate
	float2 irisTC				: TEXCOORD1;		// Iris texture coordinates
	float2 glintTC				: TEXCOORD2;		// Glint texture coordinates
	float3 vColor				: TEXCOORD3;		// Vertex-lit color
	
	float4 worldPos_projPosZ	: TEXCOORD7;		// Necessary for pixel fog
	
};

VS_OUTPUT main( const VS_INPUT v )
{
	VS_OUTPUT o;

	bool bDynamicLight = DYNAMIC_LIGHT ? true : false;
	bool bStaticLight = STATIC_LIGHT ? true : false;

	float4 vPosition = v.vPos;
	float3 dummy = v.vPos.xyz;		// dummy values that can't be optimized out

#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING
	ApplyMorph( v.vPosFlex, vPosition.xyz );
#else
	ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, dummy, vPosition.xyz );
#endif

	// Transform the position and dummy normal (not doing the dummy normal causes invariance issues with the flashlight!)
	float3 worldNormal, worldPos;
	SkinPositionAndNormal( 
		g_bSkinning, 
		vPosition, dummy,
		v.vBoneWeights, v.vBoneIndices,
		worldPos, worldNormal );

#if INTRO
	WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, dummy, dummy, dummy );
#endif

	// Transform into projection space
	float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj );
	o.projPos = vProjPos;
	vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ );
	o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z );

#if !defined( _X360 )
	// Set fixed-function fog factor
	o.fog = CalcFog( worldPos, vProjPos, g_FogType );
#endif

	// Normal = (Pos - Eye origin) - just step on dummy normal created above
	worldNormal = worldPos - cEyeOrigin;

	// Normal -= 0.5f * (Normal dot Eye Up) * Eye Up
	float normalDotUp = -dot( worldNormal, cHalfEyeballUp) * 0.5f;
	worldNormal = normalize(normalDotUp * cHalfEyeballUp + worldNormal);

	// Vertex lighting
#if ( USE_STATIC_CONTROL_FLOW || defined ( SHADER_MODEL_VS_3_0 ) )
	o.vColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert );
#else
	o.vColor = DoLightingUnrolled( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS );
#endif

	// Texture 0 is the base texture
	// Texture 1 is a planar projection used for the iris
	// Texture 2 is a planar projection used for the glint
	o.baseTC    = v.vTexCoord0;
	o.irisTC.x  = dot( cIrisProjectionU,  float4(worldPos, 1) );
	o.irisTC.y  = dot( cIrisProjectionV,  float4(worldPos, 1) );
	o.glintTC.x = dot( cGlintProjectionU, float4(worldPos, 1) );
	o.glintTC.y = dot( cGlintProjectionV, float4(worldPos, 1) );

	return o;
}