Jump to content
  • Advertisement
Sign in to follow this  
Kjell Andersson

Blinn-Phong artifact in shader

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!