# Problem with specular highlighting

13 replies to this topic

### #1Goz

Senior Member

• Members
• 575 posts

Posted 22 August 2007 - 09:15 PM

I've having a bit of a problem with my specular highlight. Im sure im just doing something stupid but i can't figure out what.

Here is an image of the wrong highlight:

http://www.trueharmo...ongSpecular.jpg

Now at first i thought it was my specular map so i added the n . h directly and got the same result. I can only assume this is something to do with my raising to the power of 1024.

This is my HLSL code



{

// Excessive view transform inverse per-pixel ... should be done CPU side once really.

float4x4	ViewInv				= inverse( View );

// Can same time by passing in the Camera position in view space.

float3		CameraPosition		= mul( float4( 0, 0, 0, 1 ), ViewInv );

// Build a light to fragment vector.

float3		LightDir			= input.PixelPos - PointLight.Position;

float		LightDist			= length( LightDir );

LightDir						= normalize( LightDir );

// Cheesy attenuation.  Should use a betetr attenuation function.

float		Attenuation			= 1.0f;//saturate( PointLight.Range - LightDist ) / PointLight.Range;

//vector from eye to fragment

float3		EyeVector			= normalize( input.PixelPos - CameraPosition );

// Sample the normal map (Specular Map is held in w)

float4		Normal				= tex2D( NormalSampler, input.UV );

Normal.xyz						= (Normal.xyz * 2) - 1;

// Build the tangent frame matrix.

float3x3	tangentFrame		= { input.Tangent, input.BiTangent, input.Normal };

// Transform the Normal.

Normal.xyz						= normalize( mul( Normal.xyz, tangentFrame ) );

// Sample the Diffuse texture.

float4		Diffuse				= tex2D( DiffuseSampler, input.UV );

// Do the N . L

float		nDotl				= saturate( dot( Normal.xyz, -LightDir ) );

float4		ColourOut			= (nDotl * float4( PointLight.Color, 1.0 ) * input.Diffuse * Attenuation) * Diffuse;

// Build the half vector.

float3		halfVec				= normalize( -EyeVector + -LightDir );

// Do the N . H

float		nDoth				= dot( halfVec, Normal.xyz );

// Raise to a specular power (1024 by default).

nDoth							= pow( nDoth, SpecularPower );

// Multiply by specular map, light colour and per-vertex specular.

ColourOut						+= nDoth; //* Normal.w * float4( PointLight.Color, 1.0 ) * input.Specular;

return ColourOut;

}



If i change the last line to simply output nDoth i still get the wrong highlight. Can i really not raise it to such a high power or is there something im just failing to spot?

Any ideas would be much appreciated because i really do prefer the nice high power :)

### #2Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 23 August 2007 - 12:47 AM

It looks like some kind of precision issue. The only thing that looked possibly wrong in your code was you're not normalizing the normal vector after you get it out of the texture. That might be the problem.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #3Goz

Senior Member

• Members
• 575 posts

Posted 23 August 2007 - 09:31 AM

Reedbeta said:

It looks like some kind of precision issue. The only thing that looked possibly wrong in your code was you're not normalizing the normal vector after you get it out of the texture. That might be the problem.

I did consider that problem. I am, however, normalising the normal after transforming it into world space.

I also tried normalising as you suggest and got exactly the same error. I even tried normalising in both places to no avail.

Its a bit of an annoying problem :(

### #4Kenneth Gorking

Senior Member

• Members
• 939 posts

Posted 23 August 2007 - 03:03 PM

A specular power of 1024 seems a bit high... How does it look if you use 16 or 32?
"Stupid bug! You go squish now!!" - Homer Simpson

### #5Goz

Senior Member

• Members
• 575 posts

Posted 23 August 2007 - 07:11 PM

Kenneth Gorking said:

A specular power of 1024 seems a bit high... How does it look if you use 16 or 32?

Well the closer i get to 1 the less obvious it is ... but at 16 and 32 the highlight looks total pants :( I WANT the very sharp highlight ... Still doesn't explain what im doing wrong cos i've done this before (alas it was for a job so i don't have the code handy to compare against). Its very strange though ...

Just did a quick check and replaced the Normal map normal with, simply, float4( 0.0, 0.0, 1.0, 1.0 ) and thats fine. So it must be something im doing TOTALLY wrong in my normal map .. would love to know what though ...

Any ideas?

### #6Goz

Senior Member

• Members
• 575 posts

Posted 23 August 2007 - 07:18 PM

Reedbeta said:

It looks like some kind of precision issue. The only thing that looked possibly wrong in your code was you're not normalizing the normal vector after you get it out of the texture. That might be the problem.

Btw ... when you say that do you mean doing the following?

Normal.xyz = normalize( (Normal.xyz * 2) - 1 );

or

Normal.xyz = ( normalize( Normal.xyz ) * 2) - 1 );

The first would seem the more correct method. That second just doesn't work in my head ... Mind either way you still see the nasty effect ...

### #7Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 24 August 2007 - 12:43 AM

The first is the one that I meant, but as you pointed out you normalize it after transforming it into world-space (I missed that before), which is actually better. So, forget what I said
reedbeta.com - developer blog, OpenGL demos, and other projects

### #8Goz

Senior Member

• Members
• 575 posts

Posted 24 August 2007 - 10:56 AM

While having a good think about this i think its because my bump map is just spread too thinly over the HUGE floor poly.

Im not sure it can be eliminated as a result of this ... unless i take multiple samples from the normal map and blend them myself (which seems extreme ;)). Damn those test cases ...

### #9Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 24 August 2007 - 03:20 PM

...you do have bilinear filtering turned on for your normal map, right?
reedbeta.com - developer blog, OpenGL demos, and other projects

### #10Goz

Senior Member

• Members
• 575 posts

Posted 28 August 2007 - 09:16 AM

Reedbeta said:

...you do have bilinear filtering turned on for your normal map, right? ;)

Strangely ... yes i do ;)

### #11J22

Member

• Members
• 92 posts

Posted 28 August 2007 - 06:40 PM

Looks like pixel shader precision issue. Which shader model are you using? You might want to consider look-up texture for specular power instead of using pow.

### #12Sean H.

Member

• Members
• 39 posts

Posted 28 August 2007 - 09:59 PM

how big is the face? if it is a precision issue, you may be able to fix it by increasing the size of the face.

### #13Goz

Senior Member

• Members
• 575 posts

Posted 29 August 2007 - 02:53 PM

J22 said:

Looks like pixel shader precision issue. Which shader model are you using? You might want to consider look-up texture for specular power instead of using pow.

TBH the precision issue itself appears to be to do with the bit depth of the bump map itself rather than anything else ...

### #14J22

Member

• Members
• 92 posts

Posted 30 August 2007 - 06:13 PM

Okay, just thought because I have seen similar specular banding artifact with high exponents in older shader model hardware. I have never seen normalmaps precision generating that kind of artifact, even when DXT compressed.

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users