struct outPixel
{
  float4 colour  : COLOR0;
};

// General functions

// Expand a range-compressed vector
half4 expand(half4 v)
{
    return v * 2 - 1;
}
half3 expand(half3 v)
{
    return v * 2 - 1;
}
half2 expand(half2 v)
{
    return v * 2 - 1;
}
half1 expand(half1 v)
{
    return v * 2 - 1;
}

// Returns light direction from light position and vertex position
half3 getLightDirection(float4 lightPosition, float4 position)
{
    // calculate tangent space light vector
    // Get object space light direction
    // Non-normalised since we'll do that in the fragment program anyway
    return lightPosition.xyz -  (position.xyz * lightPosition.w);
}

// Returns eye direction from eye position and vertex position
half3 getEyeDirection(float3 eyePosition, float4 position)
{
    return eyePosition - position.xyz;
}

// Returns a Tangent Binormal Normal matrix
half3x3 getTBNMatrix(float3 tangent, float3 normal)
{
    // Calculate the binormal (NB we assume both normal and tangent are
    // already normalised)
    // NB looks like nvidia cross params are BACKWARDS to what you'd expect
    // this equates to NxT, not TxN
    float3 binormal = cross(tangent, normal);
	
    // Form a rotation matrix out of the vectors
    return half3x3(tangent, binormal, normal);
}

// Returns expanded normal vector from texture map
half3 getNormalMapVector(sampler2D normalMap, float2 uv)
{
    // get bump map vector, again expand from range-compressed
    return expand(tex2D(normalMap, uv).xyz);
}

// Returns displacement vector from normalmaps alpha channel
half getDisplacement(sampler2D normalMap, float2 uv, half scale, half bias)
{
    // get the height using the tex coords
    half height = tex2D(normalMap, uv).a;

    // calculate displacement	
    return (height * scale) + bias;
}

// Returns a specular component from normal vector, specular colour and specular power
half3 getSpecularComponent(float3 normal, float3 halfAngle, float3 specularcolour, float specularPower)
{
    return pow(saturate(dot(normal, halfAngle)), specularPower) * specularcolour;
}

// Returns a per-pixel lighted component from normal vector, lightdir and colour
half3 getLightingComponent(float3 normal, float3 lightDir, float3 colour)
{
    return saturate(dot(normal, lightDir)) * colour;
}
