/*=============================================================================
	ScreenAlignedVertexFactory.hlsl: Local vertex factory shader code.
	Copyright © 2004-2005 Epic Games, Inc. All Rights Reserved.
=============================================================================*/

#if !USE_HW_INSTANCING
float4x4 LocalToWorld; // contains inverse view rotation(s)
//float4x4 PreviousLocalToWorld;
float3x3 WorldToLocal;
//float4 ShadowCoordinateScaleBias;
float4 CameraPos;
#endif

struct vertexInput
{
	float4	Position	: POSITION0;
	float4	Offset  	: POSITION1;
	half3	TangentX	: TANGENT;
	half3	TangentY	: BINORMAL;
	half3	TangentZ	: NORMAL;
	float4	Color		: COLOR;
#if NUM_USER_TEXCOORDS
	float2	UserTexCoords[NUM_USER_TEXCOORDS] : TEXCOORD0;
#endif
	//float2	LightMapCoordinate : COLOR;

#if USE_HW_INSTANCING
	float4x3 LocalToWorld : BLENDINDICES0;  // contains inverse view rotation(s)
	float3x3 WorldToLocal : BLENDINDICES3;
	//float4 ShadowCoordinateScaleBias : BLENDWEIGHT3;//BLENDWEIGHT6;
	float4 CameraPos : BLENDWEIGHT4;
#endif
};

struct vertexFactoryInterpolants
{
#if WORLD_COORDS
	// xyz=normal w=determinant
	float4	TangentBasisNormal	: COLOR0;
	float3	TangentBasisTangent	: COLOR1;
#endif
	float4	Color : COLOR2;
//#if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate.
//	float2	LightMapCoordinate					: TEXCOORD0;
//#if NUM_USER_TEXCOORDS
//	float2	UserTexCoords[NUM_USER_TEXCOORDS]	: TEXCOORD1;
//#endif
//#else
#if NUM_USER_TEXCOORDS
	float2	UserTexCoords[NUM_USER_TEXCOORDS]	: TEXCOORD0;
#endif
//#endif
};

userShaderInput getUserShaderInputs(vertexFactoryInterpolants Interpolants)
{
	userShaderInput	Result;
#if NUM_USER_TEXCOORDS
	for(int CoordinateIndex = 0;CoordinateIndex < NUM_USER_TEXCOORDS;CoordinateIndex++)
		Result.UserTexCoords[CoordinateIndex] = Interpolants.UserTexCoords[CoordinateIndex];
#endif
	Result.TangentNormal = Result.TangentCameraVector = Result.TangentReflectionVector = Result.TangentLightVector = Result.ScreenPosition = 0;
#if WORLD_COORDS
	Result.TangentBasisInverse = calcInvTangentBasis(Interpolants.TangentBasisNormal,Interpolants.TangentBasisTangent);
#endif
	Result.UserVertexColor = Interpolants.Color;
	return Result;
}

#if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate.
float2 getLightMapCoordinate(vertexFactoryInterpolants Interpolants)
{
	return float2(0,0);
}
#endif

float4 calcWorldPosition(vertexInput Input)
{
	// if the distance between the camera and the offset exceeds the max dist then move the quad to the
	// camera position so it is clipped
#if USE_HW_INSTANCING
	float3 dist = float3(Input.CameraPos.xyz) - float3(Input.Offset.xyz);
	float choice = step (Input.CameraPos.w, dot(dist,dist));
	return lerp ((float4(mul(Input.Position - Input.Offset,Input.LocalToWorld),1) + Input.Offset, 
		float4(Input.CameraPos.xyz,1.0f), choice);
#else
	float3 dist = float3(CameraPos.xyz) - float3(Input.Offset.xyz);
	float choice = step (CameraPos.w, dot(dist,dist));
	return lerp (mul(LocalToWorld,Input.Position - Input.Offset) + Input.Offset, 
		float4(CameraPos.xyz,1.0f), choice);
#endif
}

float4 vertexFactoryGetWorldPosition(vertexInput Input,out vertexFactoryInterpolants Interpolants)
{
#if NUM_USER_TEXCOORDS
	for(int CoordIndex = 0;CoordIndex < NUM_USER_TEXCOORDS;CoordIndex++)
		Interpolants.UserTexCoords[CoordIndex] = Input.UserTexCoords[CoordIndex];
#endif

	Interpolants.Color = Input.Color;

//#if USE_HW_INSTANCING
//	#if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate.
//		Interpolants.LightMapCoordinate = Input.LightMapCoordinate * Input.ShadowCoordinateScaleBias.xy + Input.ShadowCoordinateScaleBias.wz;
//	#endif
//#else
//	#if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate.
//		Interpolants.LightMapCoordinate = Input.LightMapCoordinate * ShadowCoordinateScaleBias.xy + ShadowCoordinateScaleBias.wz;
//	#endif
//#endif

#if WORLD_COORDS
	Interpolants.TangentBasisNormal.xyz = Input.TangentZ / 255;
	Interpolants.TangentBasisNormal.w = determinant(float3x3(Input.TangentX,Input.TangentY,Input.TangentZ) / 127.5 - 1) * 0.5 + 0.5;
	Interpolants.TangentBasisTangent = Input.TangentX / 255;	
#endif

	return calcWorldPosition(Input);
}

/** for depth-only pass */
float4 vertexFactoryGetWorldPositionOnly(vertexInput Input)
{
	return calcWorldPosition(Input);
}

float4 vertexFactoryGetPreviousWorldPosition(vertexInput Input,out vertexFactoryInterpolants Interpolants)
{
#if NUM_USER_TEXCOORDS
	for(int CoordIndex = 0;CoordIndex < NUM_USER_TEXCOORDS;CoordIndex++)
		Interpolants.UserTexCoords[CoordIndex] = float2(0.5, 0.5);//Input.UserTexCoords[CoordIndex];
#endif

	Interpolants.Color = Input.Color;

#if USE_HW_INSTANCING
	//#if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate.
	//	Interpolants.LightMapCoordinate = Input.LightMapCoordinate * Input.ShadowCoordinateScaleBias.xy + Input.ShadowCoordinateScaleBias.wz;
	//#endif
	return float4(mul(Input.Position - Input.Offset,Input.LocalToWorld),1) + Input.Offset;
#else
	//#if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate.
	//	Interpolants.LightMapCoordinate = Input.LightMapCoordinate * ShadowCoordinateScaleBias.xy + ShadowCoordinateScaleBias.wz;
	//#endif
	return mul(LocalToWorld,Input.Position - Input.Offset) + Input.Offset;
#endif
}

float3 vertexFactoryWorldToTangentSpace(vertexInput Input,half3 WorldVector)
{
#if USE_HW_INSTANCING
	return mul(float3x3(Input.TangentX,Input.TangentY,Input.TangentZ) / 127.5 - 1,mul(Input.WorldToLocal,WorldVector));
#else
	return mul(float3x3(Input.TangentX,Input.TangentY,Input.TangentZ) / 127.5 - 1,mul(WorldToLocal,WorldVector));
#endif
}
