# heightmap to normal map conversion question

3 replies to this topic

### #1magneeto

New Member

• Members
• 6 posts

Posted 09 January 2007 - 06:13 AM

hi,

how do i convert a heightmap to a normal map? I found two different solutions but i need a correct explanation

(i)

dx=heightmap[i][j]-heightmap[i-1][j]
dy=heightmap[i][j]-heightmap[i][j+1]
vector3d normal=(dx,dy,1)

normal.normalize()

(ii) dz1=heightmap[i][j]-heightmap[i-1][j]
dz2=heightmap[i][j]-heightmap[i][j+1]

dx=(1,0,dz1)
dy=(0,1,dz2)

normal=dx.cross(dy)

the above two procedures don't seem to be the same to me. the first one samples the heights in the X and Y directions whereas the second one defines the X and Y components as unit. which one is the correct?

### #2Reedbeta

DevMaster Staff

• 5311 posts
• LocationSanta Clara, CA

Posted 09 January 2007 - 06:51 AM

The second one is correct, but the first one is almost correct. The cross product of (1, 0, dz1) and (0, 1, dz2) is (0*dz2 - dz1*1, dz1*0 - dz2*1, 1*1 - 0*0) = (-dz1, -dz2, 1), which is the same as the first one except for the signs being flipped in the x and y coordinates. What the second one is doing is really defining two tangent vectors dx and dy, and the normal is of course the cross product of the tangents.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #3Goz

Senior Member

• Members
• 575 posts

Posted 09 January 2007 - 10:25 AM

The first one is a forward difference setup. It is used in DUDV bump mapping.

### #4Kenneth Gorking

Senior Member

• Members
• 939 posts

Posted 09 January 2007 - 03:06 PM

I always found the generated normalmaps looked too blocky using that technique, so I switched to a Sobel filter:

vector3d normal;

// Get sobel samples

float dx, dy, sobelTaps[8];

sobelTaps[0] = heightmap[i - 1][j - 1];

sobelTaps[1] = heightmap[i    ][j - 1];

sobelTaps[2] = heightmap[i + 1][j - 1];

sobelTaps[3] = heightmap[i - 1][j + 1];

sobelTaps[4] = heightmap[i    ][j + 1];

sobelTaps[5] = heightmap[i + 1][j + 1];

sobelTaps[6] = heightmap[i - 1][j    ];

sobelTaps[7] = heightmap[i + 1][j    ];

// Do y sobel filter

dy  = sobelTaps[0] * +1.0f;

dy += sobelTaps[1] * +2.0f;

dy += sobelTaps[2] * +1.0f;

dy += sobelTaps[3] * -1.0f;

dy += sobelTaps[4] * -2.0f;

dy += sobelTaps[5] * -1.0f;

// Do x sobel filter

dx  = sobelTaps[0] * -1.0f;

dx += sobelTaps[6] * -2.0f;

dx += sobelTaps[3] * -1.0f;

dx += sobelTaps[2] * +1.0f;

dx += sobelTaps[7] * +2.0f;

dx += sobelTaps[5] * +1.0f;

// Cross Product of components of gradient reduces to:

normal.x = -dx;

normal.y = -dy;

normal.z = 1;



"Stupid bug! You go squish now!!" - Homer Simpson

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

0 members, 1 guests, 0 anonymous users