// vertex programm to set up per-pixel parameters for bump-mapping

// output:
// position (camera-space)
// uv for texture map
// uv for normal map
// light direction (tangent space)
// camera direction (tangent space)
// diffuse light color with distance attenuation
// specular color

// input: 
// c0-c3  - View+Projection matrix
// c8     - obj-space light position, 1/(radius^2)
// c9     - light color
// c10    - specular color
// c11    - obj-space camera position

// constants
float4x4 transform; // c0  View+Projection matrix
float4   lightpos;  // c4  obj-space light position, 1/(radius^2)
float4   lightcol;  // c5  light color
float4   speccol;   // c6  specular color
float4   campos;    // c7  obj-space camera position

struct Input
{
	float3 pos    : POSITION;
	float2 uv     : TEXCOORD0;
	float3 normal : NORMAL;
	float3 tangent: TEXCOORD1;
};

struct Output
{
	float4 pos      : POSITION;
	float2 normal   : TEXCOORD0;
	float2 uv       : TEXCOORD1;
	float3 light    : TEXCOORD2;
	float3 view     : TEXCOORD3;
	float4 diffuse  : COLOR0;
	float4 specular : COLOR1;
};

Output main( Input src )
{
    Output dst;
    
    float4 pos= float4(src.pos, 1.0f);
	float3 light= lightpos - pos;
	float3 view= campos - pos;
    
	// transform vertex position to view-space
	dst.pos= mul(pos, transform);

	// texture interpolators
	dst.normal= src.uv;     // uv for normal map
	dst.uv= src.uv;         // uv for diffuse texture

	float3 tx= src.tangent;
	float3 tz= src.normal;
	float3 ty= cross(tx, tz);
	
	// transform light to tangent space
	dst.light.x= dot(light, tx);
	dst.light.y= dot(light, ty);
	dst.light.z= dot(light, tz);

	// transform view to tangent space
	dst.view.x= dot(view, tx);
	dst.view.y= dot(view, ty);
	dst.view.z= dot(view, tz);

	// distance attenuation
	float distance= dot(light, light);
	float intensity= saturate( 1.0f - (distance * lightpos.w) );
	
	// self shadowing term
	intensity*= saturate( dot(normalize(light), src.normal)*4 );

	dst.diffuse= lightcol * intensity;
	dst.specular= speccol * intensity;

    return dst;    
}

