PDA

View Full Version : heightmap to normal map

banafsheh
11-Mar-2007, 17:24
hello,
i have a big problem:?:
i want to know, how can i make a normal map from a height map in my fargmentshader.
i write a code . i read the height in each pixel and for nighbors. but wenn i want to calculate the height different between two of the, recieve zero.:???:

Mr.Pink
12-Mar-2007, 17:08
try this

float4 normalTap = tex2D( normalTex, texCoord );
float3 tanNormal = normalTap.xyz * 2.0 - float3( 1.0, 1.0, 1.0 );

float normalTapOver = tex2D( normalTex, texCoord + float2( 1.0 / mapSize, 0.0 ) ) * 2.0 - 1.0;
float normalTapUp = tex2D( normalTex, texCoord + float2( 0.0, 1.0 / mapSize ) ) * 2.0 - 1.0;

tanNormal *= bumpHeight;
normalTapOver *= bumpHeight;
normalTapUp *= bumpHeight;

float3 eugTanNormal = normalize( float3( tanNormal.x - normalTapOver, ( tanNormal.x - normalTapUp ), 1.0 ) );

tanNormal = eugTanNormal;

banafsheh
12-Mar-2007, 23:48
i have the code. but i recive zero.
this is my code:

i=1/512
float h=tex2D(normaltexture,normalCoords);
//[x+1,y]
float h1=tex2D(normaltexture,normalCoords+float2(1/512,0));
//[x,y+1]
float h2=tex2D(normaltexture,normalCoords+float2(0,1/512));
//[x-1,y]
float h3=tex2D(normaltexture,normalCoords+float2(-1/512,0));
//[x,y-1]
float h4=tex2D(normaltexture,normalCoords+float2(0,-1/512));

colorOUT.rgb=float3(h-h1,h-h4,h-h1);

float changepx = (h1 - h);
//colorOUT.rgb=float3(0,0,changepx);
+++++here also
float changepy = (h2 - h);
float changenx = (h3 - h);
float changeny = (h4 - h);

//tangent vector

float3 vpx = (i,0,changepx);
float3 vpy = (0,i,changepy);
float3 vnx = (-i,0,changenx);
float3 vny = (0,-i,changeny);

//normalize tangent vector

float3 vpxpy = normalize (cross(vpx,vpy));
float3 vpxny = normalize (cross(vpx,vny));
float3 vnxpy = normalize (cross(vnx,vpy));
float3 vnxny = normalize (cross(vnx,vny));

//make average

float3 vaverage=(vpxpy+vpxny+vnxpy+vnxny)/4;

//normalize average

float3 vNormal=normalize(vaverage);

//change it from [-1,1] to [0,1] and normalize it

vNormal = 2.0f * (vNormal - 0.5f);
vNormal = normalize(vNormal);

i tought it is because of my opengl code so i change
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_LINEAR);
to
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_NEAREST);
but it dident make change

i don't know what is wrong with my code

ShootMyMonkey
13-Mar-2007, 02:26
float3 vpxpy = normalize (cross(vpx,vpy));
float3 vpxny = normalize (cross(vpx,vny));
float3 vnxpy = normalize (cross(vnx,vpy));
float3 vnxny = normalize (cross(vnx,vny));

//make average

float3 vaverage=(vpxpy+vpxny+vnxpy+vnxny)/4;
Ummm... that can certainly pose a problem. Say for arguments sake that the height differences with respect to both positive and negative directions are equal... vpx cross vpy will produce a vector of a certain direction, while vpx cross vny will produce a vector of the opposite direction. Add them together, you'll get zero. Same with the nxpy + nxny. Even on the assumption that the differences are not necessarily equal, you're still very likely to get two vectors very nearly equal to each other. You need to take that into account when you're flipping axes. If you flip both of them, you're fine, but when you only flip one, what you want is a left-handed cross product.

i x j = k
j x i = -k
i x -j = -k
-j x i = k
-i x -j = k
-i x j = -k
j x -i = k
...
etc.

So float3 vaverage should be (vpxpy-vpxny-vnxpy+vnxny) * 0.25;

You'd probably be better off instead (to make it easy), just averaging differences and taking one cross product. i.e.
float changeX = (changepx - changenx) * 0.5;
float changeY = (changepy - changeny) * 0.5;

float3 tx = normalize(1, 0, changeX);
float3 ty = normalize(0, 1, changeY);

float3 vNormal = normalize(cross(tx,ty));

You might notice that I'm using 1 instead of 1/512 like you were doing. That's because the range of values in the texture are [0..1], so changeX/Y can be as large as 1, which means that if you use 1/512 and then normalize, you'll basically get a normal map which is 512x "stronger." Which is also why your near zero results were more prevalent since your presumed tangent vectors were almost always very nearly vertical.

Also, what was the point of this --
//change it from [-1,1] to [0,1] and normalize it

vNormal = 2.0f * (vNormal - 0.5f);
vNormal = normalize(vNormal);
Ummm... first of all, that code does the exact opposite of what you described in the comment, and it's something you do when your input is from a normal map which is in [0..1] and you want to map it to [-1..1]. The computations you've been doing will already give you such a normal in tangent space.

Humus
14-Mar-2007, 02:11
float2(1/512,0)

1/512 returns 0. HLSL interprets this as an integer division, just like C/C++.

banafsheh
14-Mar-2007, 14:48
thank you very much it works.:smile: