normal map from height map.

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

Recommended Posts

Hi.

Im trying to create normal maps from height maps myself. I have one height map for wich i created a normal map in a third party tool (a nvidia plugin for photoshop). That normal map looks like this.

when i use this normal map for rendering the result is this.

all good.

now I try to generate the normal map myself. The best i get is this

and the rendering result is this...

I try to generate the normal map by calculating and avaraging the 6 surrounding triangles normals for every vertex. like this.

[source]
private void testCalcNormals() {
StaticTile[][] tiles = world.staticTerrain.tiles;
StaticTile tile = tiles[10][5];//one StaticTile contains a 1024x1024 heightmap and normal map among other things.

for (int x = 0; x < 1024; x++)
{
for (int y = 0; y < 1024; y++)
{

float a1 = tile.getHeight(x-1, y-1);
float a2 = tile.getHeight(x, y-1);
float a3 = tile.getHeight(x+1, y-1);
float b1 = tile.getHeight(x-1, y);
float b2 = tile.getHeight(x, y);
float b3 = tile.getHeight(x+1, y);
float c1 = tile.getHeight(x-1, y+1);
float c2 = tile.getHeight(x, y+1);
float c3 = tile.getHeight(x+1, y+1);

float w = 100f;

Vector3 A1 = v(-w,a1,-w);
Vector3 A2 = v(0,a2,-w);
Vector3 A3 = v(w,a3,-w);
Vector3 B1 = v(-w,b1,0);
Vector3 B2 = v(0,b2,0);
Vector3 B3 = v(w,b3,0);
Vector3 C1 = v(-w,c1,w);
Vector3 C2 = v(0,c2,w);
Vector3 C3 = v(w,c3,w);

Vector3 t1 = surfaceNormal(B2, A2, B3);
Vector3 t2 = surfaceNormal(B2, B3, C3);
Vector3 t3 = surfaceNormal(B2, C3, C2);
Vector3 t4 = surfaceNormal(B2, C2, B1);
Vector3 t5 = surfaceNormal(B2, B1, A1);
Vector3 t6 = surfaceNormal(B2, A1, A2);

normal.normalize();
tile.setNormal(x, y, normal);

}
}
}

private static Vector3 surfaceNormal(Vector3 c1, Vector3 c2, Vector3 c3)
{
Vector3 edge1 = new Vector3(c2.x - c1.x, c2.y - c1.y, c2.z - c1.z);
Vector3 edge2 = new Vector3(c3.x - c1.x, c3.y - c1.y, c3.z - c1.z);

Vector3 normal = edge1.cross(edge2);
normal.normalize();

return normal;
}[/source]

What am I doing wrong here?
Edited by Wilhelm van Huyssteen

Share on other sites

Not spent much time examining your code, because there's a simpler way to calculate normals from a height map without even having to worry about the triangulation. You pretty much just pass a 3x3 sobel filter kernel over your height map data. There's some code in this link (Kenneth Gorking's post): http://devmaster.net/forums/topic/6611-heightmap-to-normal-map-conversion-question/

Share on other sites
If you're doing a simple average of your normals, that means that some of them are going to have negative values for X and Y. These need to be converted so that they fall in the (0,1) range, with 0.5 meaning 0. That is, multiply your X and Y components by 0.5 then add 0.5 after your normalize step. Otherwise, you end up with negative values for red or green color components, which is not what you want. A "neutral" (non-perturbed) vector in a normal map encoded like this (ie, the color representing a (0,0,1) vector relative to the normal of the face) is represented by the color (128,128,255) which is why normal maps in tangent space have that cool bluish hue.

Share on other sites

Thnx. getting the normals into the 0,1 range solved the problem.

Share on other sites

Your "failed" normal maps looks awesome :D

^^

Share on other sites

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