Advertisement Jump to content
Sign in to follow this  

Bumpmap normals

This topic is 5055 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

When I convert a say 256x256 grayscale bumpmap into normals i take the difference in height(grayscale) between pixel u,u+1 and v,v+1. This works but is will actually result in the normal at (u+0.5,v+0.5). I could just as well have sampled u-1,u and v-1,v and gotten the sample of (u-0.5,v-0.5). Is there a way to take all the slopes around u,v into account instead of arbitrarily measurement to "the left or to the right". What I want is some pseudocode for sampling heights around u,v to get a normal that is affected by its surrounding pictures on ALL sides.

Share this post

Link to post
Share on other sites
Depends if you're doing that on the fly (rendering time) or not.
On the fly: you can take the partial derivative around the, say bilinearly filtered, u and v +/-1. That works ok, but it's far from perfect like you've noticed.

If you can preprocess that into a proper normal map, then you have more options; ie a Sobel or Prewitt filtering does wonder sometimes, but it depends on the input.

Check nVidia's photoshop normal map filter plugin to get an idea of what makes sense.

Share this post

Link to post
Share on other sites
You could take the difference between pixels u+1 and u-1 (resp. v+1 and v-1).
This is called "centered difference" and is actually the sum of right difference and left difference:
(h(u+1,v)-h(u,v)) + (h(u,v)-h(u-1,v)) = h(u+1,v)-h(u-1,v)
(same for v-differences).

Share this post

Link to post
Share on other sites
Height maps can be looked upon as function of Y with the independent variables being X and Z (i am assuming OpenGL, Right Hand Coordinate System ).
Now mathematically the surface normal can be found out by:

N = - dy/dx i + j - dy/dz k

and ofcourse, dont forget to normalize N later on.

Now, how do u calculate those dy/dx and dy/dz terms are all ur choice, u can simple do this

to find dy/dx at a point (X,Z)

dy/dx[X,Z] = (height(X+1,Z) - height(X,Z)) / 1

or maybe to take a sort of average we can do this

dy/dx[X,Z] = (height(X+1,Z) - height(X-1,Z)) / 2

Similary we can find out

dy/dz[X,Z] = (height(X,Z+1) - height(X,Z-1)) / 2

now simply plugin this values into the first equation.. (there will be some errors though, but we can always live with these errors )

Normalize N and then convert them to color space values

R = (Nx + 1) / 2;
G = (Nz + 1) / 2;
B = (Ny + 1) / 2;

Notice that in the above calculation we have mapped Nz to G (Green) channel.. well thats purely because of the custom that normal maps have up-vectors to be the Blue channel. But you can always change that custom for your own application. But this way, making B the up vector, u make ur normal map PORTABLE :P

Share this post

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

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!