//Shadow vertex shader - calculates output and view positions of light sources

cbuffer MatrixBuffer : register(b0)
{
	matrix worldMatrix;
	matrix viewMatrix;
	matrix projectionMatrix;
	matrix sunViewMatrix;
	matrix sunProjectionMatrix;
	matrix spotViewMatrix;
	matrix spotProjectionMatrix;
	matrix hillViews[6];
	matrix hillProjections[6];
};

struct InputType
{
	float4 position : POSITION;
	float2 tex : TEXCOORD0;
	float3 normal : NORMAL;
};

struct OutputType
{
	float4 position : SV_POSITION;
	float2 tex : TEXCOORD0;
	float3 normal : NORMAL;
	float4 sunViewPos : TEXCOORD1;
	float4 spotViewPos : TEXCOORD2;
	float3 worldPosition : TEXCOORD3;
	float4 hillViewPositions[6] : TEXCOORD4;
};


OutputType main(InputType input)
{
	OutputType output;

	//Calculate the position of the vertex against the world, view, and projection matrices.
	output.position = mul(input.position, worldMatrix);
	output.position = mul(output.position, viewMatrix);
	output.position = mul(output.position, projectionMatrix);

	//Calculate the position of the sun
	output.sunViewPos = mul(input.position, worldMatrix);
	output.sunViewPos = mul(output.sunViewPos, sunViewMatrix);
	output.sunViewPos = mul(output.sunViewPos, sunProjectionMatrix);

	//Calculate the position of the spot light
	output.spotViewPos = mul(input.position, worldMatrix);
	output.spotViewPos = mul(output.spotViewPos, spotViewMatrix);
	output.spotViewPos = mul(output.spotViewPos, spotProjectionMatrix);

	//Calculate the positions of the hill point light in each of the directions
	for (int i = 0; i < 6; i++) 
	{
		output.hillViewPositions[i] = mul(input.position, worldMatrix);
		output.hillViewPositions[i] = mul(output.hillViewPositions[i], hillViews[i]);
		output.hillViewPositions[i] = mul(output.hillViewPositions[i], hillProjections[i]);
	}

	//Output the texture coordinates, calculate the normals
	output.tex = input.tex;
	output.normal = mul(input.normal, (float3x3)worldMatrix);
	output.normal = normalize(output.normal);

	//Output the world position
	output.worldPosition = mul(input.position, worldMatrix).xyz;

	return output;
}