float4x4 matWorldViewProj;	
float4x4 matWorld;	
float4 LightDir0;
float4 LightColor0;
float4 LightColorSpec0;
float4 EyePoint;

float4 DiffuseIn;
float4 AmbientIn;
float SpecularPower;
float4 SpecularColor;

bool NormalMapSet;
bool SpecMapSet;

bool NormaMapping;
bool TextureSpaceMapping;
bool ShowTexture;
bool ShowSpecular;
float ScaleFactor;

texture ColorMap;
sampler ColorMapSampler = sampler_state
{
   Texture = <ColorMap>;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
   AddressU  = Wrap;
   AddressV  = Wrap;
};

texture BumpMap;
sampler BumpMapSampler = sampler_state
{
   Texture = <BumpMap>;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
   AddressU  = Wrap;
   AddressV  = Wrap;
};

texture SpecMap;
sampler SpecMapSampler = sampler_state
{
   Texture = <SpecMap>;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
   AddressU  = Wrap;
   AddressV  = Wrap;
};

// -------------------------------------------------------------
// Output channels
// -------------------------------------------------------------
struct VS_OUTPUT_1
{
    float4 Pos  : POSITION;
    float2 Tex : TEXCOORD0;
    float3 Light : TEXCOORD1;
    float3 View : TEXCOORD2;
};

// -------------------------------------------------------------
// vertex shader function (input channels)
// -------------------------------------------------------------
VS_OUTPUT_1 VS_NormalMap(float4 Pos : POSITION, float2 Tex : TEXCOORD, float3 Normal : NORMAL, float3 Tangent : TANGENT, float3 Binormal : BINORMAL  )
{
    VS_OUTPUT_1 Out = (VS_OUTPUT_1)0;

    Out.Pos = mul(Pos, matWorldViewProj);	// transform Position
    
    // compute the 3x3 tranform matrix 
    // to transform from world space to tangent space
    float3x3 worldToTangentSpace;
    worldToTangentSpace[1] = normalize(mul(cross(Tangent, Normal), matWorld));
    worldToTangentSpace[2] = normalize(mul(Normal, matWorld));
    worldToTangentSpace[0] = normalize(cross(Normal, worldToTangentSpace[1]));

    Out.Tex = Tex;
    
    float4 PosWorld = mul(Pos, matWorld);	

    if(TextureSpaceMapping)
    {
		Out.Light = mul(worldToTangentSpace, LightDir0); 	// L
		Out.View = mul(worldToTangentSpace, EyePoint - PosWorld);	// V
    }
    else
    {
		Out.Light = mul(matWorld, LightDir0); 	// L
		Out.View = mul(matWorld, EyePoint - PosWorld);	// V
    }
    
   return Out;
}

// -------------------------------------------------------------
// Pixel Shader (input channels):output channel
// -------------------------------------------------------------
float4 PS_NormalMap(float2 Tex: TEXCOORD0, float3 Light : TEXCOORD1, float3 View : TEXCOORD2) : COLOR
{
    // fetch color map
    float4 Color;
    float4 ColorAmbient;
    if(ShowTexture)
    {
		Color = tex2D(ColorMapSampler, Tex)*DiffuseIn;
		ColorAmbient = tex2D(ColorMapSampler, Tex)*AmbientIn;
	}
    else
    {
		Color = DiffuseIn;
		ColorAmbient = AmbientIn;
	}	

    // bump map
    float3 Normal;
    if(NormalMapSet)
    {
		Normal = (2*(tex2D(BumpMapSampler, Tex)))- 1.0;
	}
	else
	{
		Normal.xy = 0;
		Normal.z = 1;
	}
	
    float3 LightDir = normalize(Light);	// L
    float3 ViewDir = normalize(View);	// V

	// diffuse component
    float Diffuse = dot(Normal, LightDir);
    float diffuseColor = saturate(Diffuse);  

	//
	if(ShowSpecular)
	{
		if(SpecMapSet)
		{
			SpecularColor = tex2D(SpecMapSampler, Tex)*DiffuseIn;
		}

		float Specular = 0.0;
		float3 Reflect = normalize(2*Diffuse*Normal - LightDir);
		float baseSpecular = dot(Reflect, ViewDir);
		if(baseSpecular > 0.0f)
			Specular = pow(saturate(baseSpecular), SpecularPower);

		return ColorAmbient + LightColor0*Color*diffuseColor + LightColorSpec0*Specular*SpecularColor;
	}
    else
    {
		return ColorAmbient + LightColor0*Color*diffuseColor;
    }    
}

//--------------------------

sampler s0 : register(s0);



// -------------------------------------------------------------
// 
// -------------------------------------------------------------
technique T_NormalMap
{
    pass P0
    {
        Sampler[0] = (ColorMapSampler);		
        Sampler[1] = (BumpMapSampler);		
    
        // compile shaders
        VertexShader = compile vs_1_1 VS_NormalMap();
        PixelShader  = compile ps_2_0 PS_NormalMap();
    }
}