This Cg shader works nicely and has already been partially optimised by pre-combining light & material values into the lightXXX parameters:
void lighting_phong_perpixel_VP(
in float4 position : POSITION,
in float3 normal : NORMAL,
in float2 texCoord0 : TEXCOORD0,
out float4 oPosition : POSITION,
out float4 objectPos : TEXCOORD0,
out float3 oNormal : TEXCOORD1,
out float2 oTexCoord0: TEXCOORD2,
uniform float4x4 worldViewProj)
{
oPosition = mul(worldViewProj, position);
objectPos = position;
oNormal = normal;
oTexCoord0 = texCoord0;
}
void lighting_phong_perpixel_FP(
in float4 position : TEXCOORD0,
in float3 normal : TEXCOORD1,
in float2 uv0 : TEXCOORD2,
out float4 color : COLOR,
uniform float3 lightAmbient,
uniform float3 lightDiffuse,
uniform float3 lightSpecular,
uniform float shininess,
uniform float4 lightPosition,
uniform float3 eyePosition,
uniform sampler2D texture)
{
float3 N = normalize(normal);
float3 texColor = tex2D(texture, uv0).xyz;
// calculate diffuse & specular lighting coefficients
float3 L = normalize(lightPosition.xyz - (position * lightPosition.w));
float3 V = normalize(eyePosition - position.xyz);
float3 H = normalize(L + V);
float4 lighting = lit(dot(N,L),dot(N,H),shininess);
float3 ambient = texColor * lightAmbient;
float3 diffuse = texColor * lightDiffuse * lighting.y;
float3 specular = lightSpecular * lighting.z;
color.rgb = ambient + diffuse + specular;
color.a = 1;
}
I was thinking that I should somehow be able to multiply the vector result of lit() with a vector (texColor,texColor,1,1) in some sort of matrix, so ambient, diffuse & specular can be calculated in one operation. But I am rusty at matrices... can this be done and would it actually be faster?
Also, do I need to re-normalise the normal or can I expect it to be close enough as a result of interpolation?
Note I know I could pull stuff into the VS but that's a separate topic, this is deliberately doing it all perpixel as very large polys are involved.