I'm implementing Blinn-Phong lighting in a pixel shader and is getting an artifact that I don't like. I'm tossing out a screenshot here to ask if this is normal for Blinn-Phong or if I have gotten something wrong with my calculations.
[attachment=29316:BlinnPhongArtifact.jpg]
The light source is coming from behind the sphere and is directed towards the viewer. It is supposed to be a directional light.
On the screenshot to the left the specular light is barely visible on the rim, which is perfectly fine. The problem occurs when moving a bit further behind the sphere. The specular light then becomes a cone and is detached from the rim in an unnatural way. Moving further behind the sphere makes it fade away but it keeps moving inwards the sphere before it disappears.
Lets toss in the code here as well if you want to inspect it (beware, experimental code that is not production-worthy).
struct VertDataIn {
float4 Position : POSITION;
float3 Normal : NORMAL;
float4 Color : COLOR;
float2 Texture : TEXCOORD0;
};
struct VertDataOut {
float4 Position : POSITION;
float4 Color : COLOR;
float2 Texture : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 WorldPosition : TEXCOORD2;
};
VertDataOut VS_Main(VertDataIn In)
{
VertDataOut Out;
Out.Texture = In.Texture.xy;
In.Position.w = 1;
Out.Position = mul(In.Position, g_worldViewProjectionTransform);
Out.Color = In.Color * g_diffuseColor;
Out.Normal = mul(In.Normal, g_worldTransform);
Out.WorldPosition = mul(In.Position, g_worldTransform);
return Out;
}
ColorPair CalculateDirectionalLightBlinnPhong(float3 N, float3 V, int i)
{
ColorPair Out;
float3 L = -normalize(g_directionalLights[i].dir);
float NdotL = dot(N, L);
Out.ColorDiffuse = g_directionalLights[i].ambient;
Out.ColorSpecular = 0;
if (NdotL > 0.0f) {
Out.ColorDiffuse += NdotL * g_directionalLights[i].diffuse;
}
float3 H = normalize(L + V);
Out.ColorSpecular = pow(saturate(dot(H, N)), g_materialPower) * g_directionalLights[i].specular;
return Out;
}
float4 PS_Main(VertDataOut Input) : COLOR
{
float4 col = Input.Color;
if (g_hasDiffuseTexture) {
col *= tex2D(Sampler, Input.Texture);
}
// Directional lights
float4 diffuseColor = float4(0, 0, 0, 0);
float4 specularColor = float4(0, 0, 0, 0);
for(int i = 0; i < g_numDirectionalLights; i++) {
ColorPair colorOut = CalculateDirectionalLightBlinnPhong(normalize(Input.Normal), normalize(g_cameraPosition - Input.WorldPosition), i);
diffuseColor += colorOut.ColorDiffuse;
specularColor += colorOut.ColorSpecular;
}
col.rgb *= (diffuseColor.rgb + specularColor.rgb);
return col;
}