# Specular Highlights Disappear Up Close

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

## Recommended Posts

I've noticed that in my engine the specular highlights for shiny objects go away for objects that are closer to the camera. Interestingly, increasing the scale factor for the objects allows the camera to get much closer before the highlights disappear. Therefore, I don't think this is an inherent property of the geometry of specular lighting.

I am using a normalized Blinn-Phong lighting model and this issue exists for both point and directional light sources. I've checked my shader against examples online and it seems to match them. In addition, the same behavior was observed with the Phong lighting model.

I've attached two screenshots showing a series of 4 shiny objects. In the first, the highlight is most prominent on the distant object and least prominent for the closest. In the second, the scene was scaled by 5x, and the highlights are similar for all objects.

Has anyone else noticed this artifact? My only guess is that there is some problem with how I am computing the normal matrix (transpose of the inverse of the upper 3x3 of model view matrix) or view-space light direction (model view matrix * world space direction), but there doesn't seem to be any negative effect on the normals themselves or the diffuse lighting.

Edit: I was just playing around with it again and found that if I calculate the view-space half vector once for the entire view, rather than per-pixel, the highlights behave the way they should.

Edited by Aressera

##### Share on other sites

Are your light, view, normal, half, etc vectors all normalized?

##### Share on other sites

Yes, I have made sure they are all normalized.

I rewrote my shader and I managed to fix the problem (even with per-pixel half vectors). The issue was how I was calculating the direction to the surface. I was using a 4D vector (x,y,z,w) to represent position, and neglecting the fact that the w component was non-zero. Therefore, the computed half vector wasn't correct.

// Old code
vec4 surfacePosition = interpolatedPosition;
vec4 surfaceDirection = normalize( surfacePosition );

// New code
vec4 surfacePosition = vec4( interpolatedPosition.xyz / interpolatedPosition.w, 1.0 );
vec4 surfaceDirection = vec4( normalize( surfacePosition.xyz ), 0.0 );


##### Share on other sites

normalize( surfacePosition ) ... normalize( surfacePosition.xyz )
Yeah you've got to be careful with that stuff! It's very easy to ask the GPU to give you unit-length 4D vector instead of a unit-length 3D vector.

Internally, modern GPU's are actually all scalar (they work with floats, not vec4's) so it's best to always use the most appropriate variable types, e.g. a vec3 instead of a vec4 with an unused w component.

##### Share on other sites

normalize( surfacePosition ) ... normalize( surfacePosition.xyz )
Yeah you've got to be careful with that stuff! It's very easy to ask the GPU to give you unit-length 4D vector instead of a unit-length 3D vector.

Internally, modern GPU's are actually all scalar (they work with floats, not vec4's) so it's best to always use the most appropriate variable types, e.g. a vec3 instead of a vec4 with an unused w component.

Good to know, I guess I'm used to working with SIMD so I figured 4 component vectors would be better.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 11
• 9
• 9
• 41
• ### Forum Statistics

• Total Topics
634130
• Total Posts
3015706
×