This topic is 1159 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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;
}



##### Share on other sites

I had the same problem once, MJP has the right solution.

##### Share on other sites

Thanks!

I kind of liked the scattering of specular around the rim before multiplying with NdotL, but I guess that should not be part of the Blinn calculations but rather some subsurface scattering effect.

##### Share on other sites

Thanks!
I kind of liked the scattering of specular around the rim before multiplying with NdotL, but I guess that should not be part of the Blinn calculations but rather some subsurface scattering effect.

You can get a more accurate version of that effect by using a microfacet specular BRDF. Such a BRDF has geometry and fresnel terms that give you interesting off-specular peak behavior, but do so in a way that's more consistent with physics compared what you're using. However this does require more calculations, which can make the shader more expensive.

1. 1
2. 2
3. 3
Rutin
15
4. 4
5. 5

• 10
• 9
• 9
• 11
• 11
• ### Forum Statistics

• Total Topics
633686
• Total Posts
3013318
×