float4x4 World; 
float4x4 View;
float4x4 Project;

float3 AmbientLightColor;
float3 DiffuseColor;
float SpecularPower;

float3 EyePosition;
float3 LightDirection;
float3 LightDiffuseColor;
float3 LightSpecularColor;

struct VS_INPUT {
    float4 Position         : POSITION0;
    float3 Normal           : NORMAL0;
};

struct VS_OUTPUT {
    float4 Position         : POSITION0;
    float3 Normal           : TEXCOORD1;
    float3 ViewDirection    : TEXCOORD2;
};

VS_OUTPUT Transform(VS_INPUT Input){
    float4x4 WorldViewProject = mul(mul(World, View), Project);
    float3 ObjectPosition	= mul(Input.Position, World);
    
    VS_OUTPUT Output;
    Output.Position         = mul(Input.Position, WorldViewProject);
    Output.Normal           = mul(Input.Normal, World);
    Output.ViewDirection    = EyePosition - ObjectPosition;
    
    return Output;
}

struct PS_INPUT {
    float3 Normal           : TEXCOORD1;
    float3 ViewDirection    : TEXCOORD2;
};

float4 BasicShader(PS_INPUT Input) : COLOR0{
    float3 Normal           = normalize(Input.Normal);
    float3 ViewDirection    = normalize(Input.ViewDirection);
   
    float EdgeComponent     = saturate(dot(Normal, ViewDirection));
    float4 TotalAmbient     = 0.15 + EdgeComponent;

    float NDotL             = saturate(dot(Normal, LightDirection));
    float4 TotalDiffuse     = saturate(float4(LightDiffuseColor * NDotL,1.0));

    float3 Reflection       = normalize(2.0f * NDotL * Normal - LightDirection);
    float RDotV             = max(0.0f, dot(Reflection, ViewDirection));
    float4 TotalSpecular    = float4(saturate(LightSpecularColor * pow(RDotV, SpecularPower)), 1.0f);
    float4 FinalColor       = saturate(float4(DiffuseColor,1.0) * (TotalAmbient + TotalDiffuse) + TotalSpecular);
    FinalColor.a = 1.0;
    return FinalColor;
}

technique BasicShader {
    pass P0 {
        VertexShader = compile vs_2_0 Transform();
        PixelShader  = compile ps_2_0 BasicShader();
    }
}