uniform float4x4 World;          // World transformation
uniform float4x4 WorldViewProj;  // World * View * Projection transformation

uniform float4x4 LightView0;
uniform float4x4 LightViewProj0;

uniform float4x4 LightView1;
uniform float4x4 LightViewProj1;

uniform float4x4 LightView2;
uniform float4x4 LightViewProj2;

uniform float4x4 LightView3;
uniform float4x4 LightViewProj3;

uniform float4x4 LightView4;
uniform float4x4 LightViewProj4;

uniform float4x4 LightView5;
uniform float4x4 LightViewProj5;

uniform float3 TextureRepeat;

struct VS_OUTPUT
{
    float4 Position         : POSITION;   // vertex position
    float4 TexCoord         : TEXCOORD0;  // vertex interpolation value
    float3 Normal           : TEXCOORD1;  // vertex normal
    float3 WorldPosition    : TEXCOORD2;  // vertex world position
    float3 Light0Map        : TEXCOORD3;  // light0 shadow map
    float3 Light1Map        : TEXCOORD4;  // light1 shadow map
    float3 Light2Map        : TEXCOORD5;  // light2 shadow map
    float3 Light3Map        : TEXCOORD6;  // light3 shadow map
    float3 Light4Map        : TEXCOORD7;  // light4 shadow map
    float3 Light5Map        : TEXCOORD8;  // light5 shadow map
};

VS_OUTPUT VShaderEntry( in float3 Position : POSITION,
                        in float3 Normal   : NORMAL,
                        in float4 TexCoord : TEXCOORD0 )
{
    VS_OUTPUT Output;
    
    static float DepthScale = 0.1;

    float4 WorldPos = mul( float4( Position.x, Position.y, Position.z, 1.0f ), World );

    Output.Position = mul( float4( Position.x, Position.y, Position.z, 1.0f ), WorldViewProj );
    Output.Normal = mul( float4( Normal.x, Normal.y, Normal.z, 0.0f ), World );
    Output.WorldPosition = float3(WorldPos.x, WorldPos.y, WorldPos.z);
    Output.TexCoord = float4(TexCoord.x * TextureRepeat.x, TexCoord.y * TextureRepeat.y, 0.0, 0.0);
    
    float4 PositionPoint = float4( WorldPos.x, WorldPos.y, WorldPos.z, 1.0f );
    
    //
    // Light0
    //
    {
        float4 LightProjPos = mul( PositionPoint, LightViewProj0 );
        float4 LightViewPos = mul( PositionPoint, LightView0 );
        Output.Light0Map.x = (LightProjPos.x / LightProjPos.w) * 0.5 + 0.5;
        Output.Light0Map.y = 0.5 - (LightProjPos.y / LightProjPos.w) * 0.5;
        Output.Light0Map.z = -LightViewPos.z * DepthScale;
    }

    //
    // Light1
    //
    {
        float4 LightProjPos = mul( PositionPoint, LightViewProj1 );
        float4 LightViewPos = mul( PositionPoint, LightView1 );
        Output.Light1Map.x = (LightProjPos.x / LightProjPos.w) * 0.5 + 0.5;
        Output.Light1Map.y = 0.5 - (LightProjPos.y / LightProjPos.w) * 0.5;
        Output.Light1Map.z = -LightViewPos.z * DepthScale;
    }

    //
    // Light2
    //
    {
        float4 LightProjPos = mul( PositionPoint, LightViewProj2 );
        float4 LightViewPos = mul( PositionPoint, LightView2 );
        Output.Light2Map.x = (LightProjPos.x / LightProjPos.w) * 0.5 + 0.5;
        Output.Light2Map.y = 0.5 - (LightProjPos.y / LightProjPos.w) * 0.5;
        Output.Light2Map.z = -LightViewPos.z * DepthScale;
    }

    //
    // Light3
    //
    {
        float4 LightProjPos = mul( PositionPoint, LightViewProj3 );
        float4 LightViewPos = mul( PositionPoint, LightView3 );
        Output.Light3Map.x = (LightProjPos.x / LightProjPos.w) * 0.5 + 0.5;
        Output.Light3Map.y = 0.5 - (LightProjPos.y / LightProjPos.w) * 0.5;
        Output.Light3Map.z = -LightViewPos.z * DepthScale;
    }

    //
    // Light4
    //
    {
        float4 LightProjPos = mul( PositionPoint, LightViewProj4 );
        float4 LightViewPos = mul( PositionPoint, LightView4 );
        Output.Light4Map.x = (LightProjPos.x / LightProjPos.w) * 0.5 + 0.5;
        Output.Light4Map.y = 0.5 - (LightProjPos.y / LightProjPos.w) * 0.5;
        Output.Light4Map.z = -LightViewPos.z * DepthScale;
    }

    //
    // Light5
    //
    {
        float4 LightProjPos = mul( PositionPoint, LightViewProj5 );
        float4 LightViewPos = mul( PositionPoint, LightView5 );
        Output.Light5Map.x = (LightProjPos.x / LightProjPos.w) * 0.5 + 0.5;
        Output.Light5Map.y = 0.5 - (LightProjPos.y / LightProjPos.w) * 0.5;
        Output.Light5Map.z = -LightViewPos.z * DepthScale;
    }
    
    return Output;
}