//
// Basic Shading Effect File
//

float4 MaterialAmbient : MATERIALAMBIENT = {0.1f, 0.1f, 0.1f, 1.0f};
float4 MaterialDiffuse : MATERIALDIFFUSE = {0.8f, 0.8f, 0.8f, 1.0f};
float4 MaterialSpecular : MATERIALSPECULAR = {1.0f, 1.0f, 1.0f, 7.0f};
float4x3 TransformMatrix;
float4x4 ProjectionMatrix;

// light information
vector LightVector;
vector LightPos;
vector EyePos;
float4 LightColor;


///////////////////////////////////////////////////////
struct VS_INPUT
{
    float3  Pos             : POSITION;
    float3  Normal          : NORMAL;
    float2  Tex0            : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4  Pos     : POSITION;
    float4  Diffuse  : COLOR0;
    float4  Specular : COLOR1;
    float2  Tex0    : TEXCOORD0;
};

// Vertex Shader
VS_OUTPUT VShade(VS_INPUT i)
{
	VS_OUTPUT   o;
	
	// perform transformation
	float3 P = mul(float4(i.Pos, 1), (float4x3)TransformMatrix);
	o.Pos  = mul(float4(P, 1), ProjectionMatrix);
	i.Normal = normalize(i.Normal);
	
	// perform lighting
	// do shading - Anisotropic Ward shading
	vector VertexToEye = normalize(EyePos - float4(i.Pos, 1));
	float3 HalfVector = normalize(LightVector + VertexToEye);
	float CosTheta = dot(i.Normal, LightVector);
	float CosDelta = dot(i.Normal, VertexToEye);
	float4 FirstTerm = 1.0f / sqrt(CosTheta * CosDelta);
	
	float2 Roughness = {0.9f, 0.1f};
	float4 SecondTerm = 1.0f / (12.56 * Roughness.x * Roughness.y);
	
	float3 Direction = {0.0f, 0.0f, 1.0};
	float3 X = normalize(cross(i.Normal, Direction));
	float3 Y = normalize(cross(i.Normal, X));
	float HdotX = dot(HalfVector, X);
	float HdotY = dot(HalfVector, Y);
	float HdotN = dot(HalfVector, i.Normal);
	float A = -2.0f * (pow((HdotX / Roughness.x), 2) + pow((HdotY / Roughness.y), 2));
	float B = 1.0f + HdotN;
	float4 ThirdTerm = exp(A / B);
	float4 Irradiance = max(0.0f, CosTheta);
	
	float4 Specular = MaterialSpecular * FirstTerm * SecondTerm * ThirdTerm;
	o.Diffuse = LightColor * MaterialDiffuse * Irradiance;
	o.Specular = Specular * Irradiance;
	
	// copy texture coord
    o.Tex0  = i.Tex0;
	
	return o;
}


//////////////////////////////////////
// Techniques specs follow
//////////////////////////////////////
technique t0
{
    pass p0
    {
        VertexShader = compile vs_2_0 VShade();
    }
}