Jump to content


heightmap to normal map conversion question


3 replies to this topic

#1 magneeto

    New Member

  • Members
  • Pip
  • 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?

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 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

#3 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 575 posts

Posted 09 January 2007 - 10:25 AM

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

#4 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 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