Skip to main content
GameDev.net gamedev.net
🔒 Locked

D3DXComputeNormalMap

Started by MatuX Jul 21, 2002 at 2:26 PM 6 replies 1.8k views
Original Post
MatuX
MatuX
I''m having problems using this function... It seems it isn''t correctly creating my normals. These are the steps I''m doing: 1. Create a D3DFMT_A8 + D3DPOOL_SCRATCH texture with the dimensions (width and height) of the heightmap (lets call it pSrcTexture). 2. Lock pSrcTexture and copy the heightmap to it (this is done correctly) 3. Create another texture using FMT_R8G8B8 + POOL_SCRATCH with the dimensions of the heightmap (lets call it pDestTexture). 4. I call D3DXComputeNormalMap passing, first, the destination texture (pDestTexture), second the source texture (pSrcTexture), third NULL, flags 0, D3DX_CHANNEL_ALPHA and I''m passing an 1.0f for the Amplitude (this may be wrong as I don''t exactly know what does "Amplitude" means, and I quite don''t understand what the SDK means with "Constant value by which the height information is multiplied.", nevertheless, I''ve already sent 1.0f and 10.0f but the output is the same. 5. Finally, I copy the RGB contents of pDestTexture to my normal vector (float nx, ny, nz) dividing each value by 255 (as I understand, normals goes from 0.0f to 1.0f). The output is different on every different heightmap, so, D3DXComputeNormalMap is doing the normal processing, and I''m having weird results like, a plain heightmap will result in a 1.0,0.5,0.5 (nx, ny, nz) 1.0,0.4,0.4 1.0,0.5,0.5 1.0,0.4,0.4 (etc.) Normals output. Does anybody know what I''m doing wrong? Thanks in advance!
CrazedGenius
CrazedGenius
The purpose of the normal map is not to supply the vertex normals. Its purpose is to supply per pixel normals for things like bump mapping.

Imagine a plane with the normals facing straight up and the light source facing straight down. Imagine that plane is textured with a normal map. The information in the normal map will help to define the lighting effects for each pixel (if used effectively) and that might be very different than the per-vertex lighting effects.

When you mention copying the RGB values to your normals, which values do you copy to which normals?
EvilDecl81
EvilDecl81
It is doing exactly what it is supposed to do: The output you see is consistent with what I would expect from a fairly flat surface. What are you expecting to see?

You are interpretting your colors incorrectly, did you not take into acount byte ordering? 1.0 is Z, not X, so they are all flipped. Also, since you can''t store negative values in most texture formats, this function biases them. I.E. .5 = 0, 0 = -1, 1 = 1; To unbias,use the _bx2 modifier in the pixel shader (dont automaticlaly with the old TSS).

Amplitude is exactly that. Think of the map as a terrain, D3DXComputeNormal keeps a ratio of 1 to 1. Therefore, a value of 255 in the height map = the same distance as the width of a pixel. Amplitude adjusts this ratio, so you could say, make the ''terrain'' higher or shallower. If you make it negative then it will invert the ''terrain''. This is a tweakable value, play with it to get the effect you want.

ComputeNormalMap also a neat feature where it will tell you an aproximate ''shadow'' term and put it in alpha. Basically, how much is one pixel occluded by other pixels for a hemisphere lighting model.


EvilDecl81
MatuX
MatuX
I readed in this forum you could succesfully use D3DXComputeNormalMap to generate the needed normals to compute terrain lighting, sad I can''t find the thread anymore but I preserve some of the explanation:
quote:

D3DX has a function that calculates normals from a heightfield.
This function is generally used for DOT3 bumpmapping to figure out normals from a heightfield texture but it can be very nicely used to compute normals on a terrain. So you can get rid of all your averaging code and use a simple function: D3DXComputeNormalMap().
This normal map requires a texture with a heightfield so create a texture that load your heightmap from a file, call this function and then delete the texture. That''s it. This function has some parameters that are unclear so if you don''t understand something just post here. For example Amplitude parameter is not just height, it''s MaxVerticalHeight * (2.0f / MaxHorizontalSize).


I may be wrong, but I thought D3DXComputeNormalMap would output the normals I needed for each vertex, so, I''m copying each RGB value on each vertex XYZ normal.
MatuX
MatuX
quote:
Original post by EvilDecl81
It is doing exactly what it is supposed to do: The output you see is consistent with what I would expect from a fairly flat surface. What are you expecting to see?

You are interpretting your colors incorrectly, did you not take into acount byte ordering? 1.0 is Z, not X, so they are all flipped. Also, since you can''t store negative values in most texture formats, this function biases them. I.E. .5 = 0, 0 = -1, 1 = 1; To unbias,use the _bx2 modifier in the pixel shader (dont automaticlaly with the old TSS).

Amplitude is exactly that. Think of the map as a terrain, D3DXComputeNormal keeps a ratio of 1 to 1. Therefore, a value of 255 in the height map = the same distance as the width of a pixel. Amplitude adjusts this ratio, so you could say, make the ''terrain'' higher or shallower. If you make it negative then it will invert the ''terrain''. This is a tweakable value, play with it to get the effect you want.




If the heightmap is flat, shouldn''t all the normals be 1.0f?

Here is a screenshot of the engine running, look how the normals seems to be all wrong:
http://matux.hypermart.net/shot01.jpg

If I can''t fix this soon I think I''ll just calculate and average the normal by hand
EvilDecl81
EvilDecl81
The normals should be (0,0,1) for a flat surface.



quote:
Original post by MatuX
[quote]Original post by EvilDecl81
It is doing exactly what it is supposed to do: The output you see is consistent with what I would expect from a fairly flat surface. What are you expecting to see?

You are interpretting your colors incorrectly, did you not take into acount byte ordering? 1.0 is Z, not X, so they are all flipped. Also, since you can''t store negative values in most texture formats, this function biases them. I.E. .5 = 0, 0 = -1, 1 = 1; To unbias,use the _bx2 modifier in the pixel shader (dont automaticlaly with the old TSS).

Amplitude is exactly that. Think of the map as a terrain, D3DXComputeNormal keeps a ratio of 1 to 1. Therefore, a value of 255 in the height map = the same distance as the width of a pixel. Amplitude adjusts this ratio, so you could say, make the ''terrain'' higher or shallower. If you make it negative then it will invert the ''terrain''. This is a tweakable value, play with it to get the effect you want.




If the heightmap is flat, shouldn''t all the normals be 1.0f?

Here is a screenshot of the engine running, look how the normals seems to be all wrong:
http://matux.hypermart.net/shot01.jpg

If I can''t fix this soon I think I''ll just calculate and average the normal by hand

EvilDecl81
MatuX
MatuX
quote:
Original post by EvilDecl81
The normals should be (0,0,1) for a flat surface.



Yep, silly mistake of mine... Anyway, I''ve already fixed it... It simply was what you said, the values where biased.

Thanks

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.