cbuffer MatrixBuffer : register(vs, cb0)
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

cbuffer CameraBuffer : register(vs, cb1)
{
    float3 cameraPosition;
	float CameraBuffer_padding;
};

struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD0;
	float2 padding0 : PADDING0;
    float3 normal : NORMAL;
	float  padding1 : PADDING1;
	float3 tangent : TANGENT;
	float padding2 : PADDING2;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
	float4 worldPosition : POSITION1;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
    float3 binormal : BINORMAL;
	float3 viewDirection : TEXCOORD1;
};

PixelInputType LightVertexShader(VertexInputType input)
{
    PixelInputType output;
    float4 worldPosition;

    // Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;

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

    // Store the texture coordinates for the pixel shader.
    output.tex = input.tex;
	
/*	// compute derivations of the world position
	float3 p_dx = ddx(output.worldPosition);
	float3 p_dy = ddy(output.worldPosition);
	// compute derivations of the texture coordinate
	float2 tc_dx = ddx(input.tex);
	float2 tc_dy = ddy(input.tex);
	// compute initial tangent and bi-tangent
	float3 t = normalize( tc_dy.y * p_dx - tc_dx.y * p_dy );
	float3 b = normalize( tc_dy.x * p_dx - tc_dx.x * p_dy ); // sign inversion
	// get new tangent from a given mesh normal
	float3 n = normalize(input.normal);
	float3 x = cross(n, t);
	t = cross(x, n);
	t = normalize(t);
	// get updated bi-tangent
	x = cross(b, n);
	b = cross(n, x);
	b = normalize(b);
	mat3 tbn = mat3(t, b, n);*/

    // Calculate the normal vector against the world matrix only.
    output.normal = mul(input.normal, (float3x3)worldMatrix);
    // Normalize the normal vector.
    output.normal = normalize(output.normal);
	
	// Calculate the tangent vector against the world matrix only and then normalize the final value.
    output.tangent = mul(input.tangent, (float3x3)worldMatrix);
    output.tangent = normalize(output.tangent);

    // Calculate the binormal vector against the world matrix only and then normalize the final value.
    //output.binormal = mul(b, (float3x3)worldMatrix);
	output.binormal = cross(input.normal, input.tangent);
	output.binormal = mul(output.binormal, (float3x3)worldMatrix);
    output.binormal = normalize(output.binormal);
	
    // Determine the viewing direction based on the position of the camera and the position of the vertex in the world.
    output.viewDirection = cameraPosition.xyz - output.worldPosition.xyz;
	
    // Normalize the viewing direction vector.
    output.viewDirection = normalize(output.viewDirection);
	
    return output;
}