matrix	WorldMatrix			: register(c0);		// c0-c3
matrix	ProjViewMatrix		: register(c4);		// c4-c7
vector	CameraPosition		: register(c8);

vector	KeyLightNormal		: register(c9);
vector	FillLightNormal		: register(c10);
vector	BackLightNormal		: register(c11);

sampler Albedo				: register(s0);
sampler NormalMap			: register(s1);

vector	KeyLightColour		: register(c0);
vector	FillLightColour		: register(c1);
vector	BackLightColour		: register(c2);
vector	SpecularParameters	: register(c3);

// -------------------------------------------------------------------------
//		Datatypes
// -------------------------------------------------------------------------

struct VS_INPUT
{
	vector Position		: POSITION;
	float3 Normal		: NORMAL0;
	float3 Tangent		: NORMAL1;
	float3 Bitangent	: NORMAL2;
	float2 Texture		: TEXCOORD0;
};

struct PS_INPUT
{
	vector Position		: POSITION;
	float2 TexPosition	: TEXCOORD0;
	float3 NormalKey	: TEXCOORD1;
	float3 NormalFill	: TEXCOORD2;
	float3 NormalBack	: TEXCOORD3;
	float3 NormalCam	: TEXCOORD4;
};

struct PS_OUTPUT
{
	vector Diffuse		: COLOR0;
};

// -------------------------------------------------------------------------
//		Vertexshader
// -------------------------------------------------------------------------

PS_INPUT VertexShader(VS_INPUT input)
{
	PS_INPUT output = (PS_INPUT)0;
	
	float3 CamDirection = normalize(CameraPosition - input.Position.xyz);
//	CamDirection.x *= -1.0f;
	
	output.Position		= mul(WorldMatrix, input.Position);
	output.Position		= mul(ProjViewMatrix, output.Position);
	output.TexPosition	= input.Texture;
	
	input.Normal		= mul(WorldMatrix, input.Normal);
	input.Tangent		= mul(WorldMatrix, input.Tangent);
	input.Bitangent		= mul(WorldMatrix, input.Bitangent);
	
	float3x3 TurnMatrix = float3x3(input.Bitangent, input.Tangent, input.Normal); 
	output.NormalKey	= normalize(mul(TurnMatrix, KeyLightNormal.xyz));
	output.NormalFill	= normalize(mul(TurnMatrix, FillLightNormal.xyz));
	output.NormalBack	= normalize(mul(TurnMatrix, BackLightNormal.xyz));
	output.NormalCam	= normalize(mul(TurnMatrix, CamDirection));
	
	return output;
}

// -------------------------------------------------------------------------
//		Pixelshader
// -------------------------------------------------------------------------

PS_OUTPUT PixelShader(PS_INPUT input)
{
	PS_OUTPUT output = (PS_OUTPUT)0;
	
	vector PixelAlbedo		=	tex2D(Albedo, input.TexPosition);
	float4 TexNormal		=	tex2D(NormalMap, input.TexPosition);
	float3 PixelNormal		=	TexNormal.xyz * 2.0f - 1.0f;
	float  SpecularAmount	=	TexNormal.w;
	float3 LightNormalKey	=	input.NormalKey;
	float3 LightNormalFill	=	input.NormalFill;
	float3 LightNormalBack	=	input.NormalBack;
	float3 CameraNormal		=	input.NormalCam;
	float3 CamOverSurface	=	reflect(CameraNormal, PixelNormal);
	
	float KeyLightAmount	=	saturate(dot(PixelNormal, LightNormalKey) + KeyLightColour.w);
	float FillLightAmount	=	saturate(dot(PixelNormal, LightNormalFill) + FillLightColour.w);
	float BackLightAmount	=	saturate(dot(PixelNormal, LightNormalBack) + BackLightColour.w);
	
	float CameraAngleKey	=	dot(CamOverSurface, LightNormalKey);
	float CameraAngleFill	=	dot(CamOverSurface, LightNormalFill);
	float CameraAngleBack	=	dot(CamOverSurface, LightNormalBack);
	
	float SpecularKey		=	pow(saturate(-CameraAngleKey), SpecularParameters.x) * SpecularParameters.y * SpecularAmount;
	float SpecularFill		=	pow(saturate(-CameraAngleFill), SpecularParameters.x) * SpecularParameters.y * SpecularAmount;
	float SpecularBack		=	pow(saturate(-CameraAngleBack), SpecularParameters.x) * SpecularParameters.y * SpecularAmount;
	
	//KeyLightAmount			*=	1.0f + SpecularKey;
	//FillLightAmount			*=	1.0f + SpecularFill;
	//BackLightAmount			*=	1.0f + SpecularBack;
	
	vector KeyLight			=	KeyLightAmount * KeyLightColour;
	vector FillLight		=	FillLightAmount * FillLightColour;
	vector BackLight		=	BackLightAmount * BackLightColour;
	
	output.Diffuse.xyz		=	PixelAlbedo.xyz * (KeyLight + FillLight + BackLight);
	output.Diffuse.xyz		+=	SpecularKey;
	output.Diffuse.xyz		+=	SpecularFill;
	output.Diffuse.xyz		+=	SpecularBack;
	output.Diffuse.w		=	PixelAlbedo.w;
	
	return output;
}