Advertisement

Specular lighting working but slight bug

Started by February 12, 2019 02:45 AM
4 comments, last by dietrich 5 years, 11 months ago

Hi Guys,

Today I have added a specular lighting component to my shader and all is working well except for one anomaly. When I increase the specular power variable the specular intensity decrease. The lower the number, the higher specularity.

I can't quite put my finger on why this is.

This is the relevant code from my pixel shader;


	float4 color = input.lightColor;

	float diffuseIntensity = saturate(dot(input.normal, input.lightPos));
	color += (color * diffuseIntensity);
	color = saturate(color);

	// Specular component
	float3 reflection = normalize(2 * diffuseIntensity * input.normal - input.lightPos);

	float specularPower = 3.0f;		// **** The variable in question ****

	float4 specularIntensity = float4(0.0f, 0.0f, 0.0f, 0.0f);
	specularIntensity = pow(saturate(dot(reflection, input.lightPos)), specularPower);

	color = saturate(color + specularIntensity);

	return color;

Any ideas what I might be overlooking here?

Thanks in advance ?

[edit] Worked out the following. I needed to multiply this against the diffuse colour. 

 

Another thing I just noticed too, if I multiply the texture colour against the output, I lose the nice shiny highlights.


	//textureColor = TextureStandard.Sample(SamplerWrap, input.textureCoord);
	//color *= textureColor;
Advertisement

Hi, @DividedByZero!

Can you point to the technique you're using to calculate the specular component? It's not very clear from the code.

Looks like you're missing a view vector completely, which may be the source of the problem, since specular reflections are view-dependent. This line computes a reflected light vector:


float3 reflection = normalize(2 * diffuseIntensity * input.normal - input.lightPos);

And here you compute the dot product between the light vector and its reflection:


specularIntensity = pow(saturate(dot(reflection, input.lightPos)), specularPower);

If I'm correct, this doesn't make much sense. In the picture below, dot(reflection, input.lightPos) corresponds to angle α between l and l', which basically tells you how, how far the light is from the surface's normal. Instead you want to compute angle θ between the view vector v and the perfect reflection direction l'. To do so, substitue input.lightPos for the view vector in either one of the lines above.

Also, to take it a step further, take a look at the Blinn-Phong shading model (Wiki). It uses the half-vector between light and view direction to compute the specular, which better describes the actual physics of the process and produces more plausible result under certain conditions.

On 2/12/2019 at 6:47 AM, DividedByZero said:

Another thing I just noticed too, if I multiply the texture colour against the output, I lose the nice shiny highlights.

Make sure to multiply by the texture color before you add the specular term. For most (all?) dielectric materials (plastic, paper, fabrics, etc.), the diffuse color does not affect the specular reflection.

angles.png

@dietrich Awesome reply, mate! That cleared up a lot for me and I managed to fix up that quirk in my code.

It probably would have been more apparent once I start moving the camera around that there was a problem.

I did notice from the reference material that I was following this, just now.

The lower the specularPower value the greater the final effect is

So it turns out that the behaviour of the specularPower was correct anyway, it was just my logic thinking greater would be more. But not in this case.

But you certainly helped me squish that other 'future' bug in its tracks.

Thank you once again! You are awesome ?

@DividedByZero, no problem, glad it helped:)

This topic is closed to new replies.

Advertisement