Jump to content
  • Advertisement
Sign in to follow this  
bengaltgrs

Normal mapping issues

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

After looking through the DirectX SDK and various other resources, I wrote a program that just renders a normal mapped object, but it is not working properly and I cannot seem to find the solution. The object seems to be lit indefinitely in a horizontal line between the X and Z axis. Here is a screenshot to show you what I am talking about. (just for reference, that square is made up of 32 triangles) http://www.equalmeans.net/~chriss/NormalMapping.jpg Also, it seems to treat the lights position in the X axis the same as it does in the Z axis, meaning I can move the light left to right and it does the exact same thing as if it is moved front to back, so possibly a problem with the light vector somewhere? I am fairly certain that all the values are set properly, so I really cannot figure out where it is going wrong. I'll leave a link to my demo in case anyone wants to look through it, if not, any other help would be great. Thanks for the help, Chris http://www.equalmeans.net/~chriss/PS.zip The demo was written onto a pre-existing program from: http://moon-labs.com/ And the shader is an unaltered copy straight from: http://www.pieterg.com/Tutorials/bump_normal.php

Share this post


Link to post
Share on other sites
Advertisement
Hi there bengaltgrs,
How are you doing?

The Problem
Lighting in normal mapping is all screwy :P

The Solution
When working with normal maps you must make sure that your mesh contains the following information to be sent to the shader.
Position, Normal, Texture, Tangent, BiNormal
I have had a look at your source and I couldn't find anywhere where your actually calculate the Tangent and BiNormal information. This means that the lighting calculations might go al messy since you create a BiTangent transformation matrix and transform your light to tangent space using this matrix.

Something like the following should work.

D3DVERTEXELEMENT9 elements[] =
{
{ 0, sizeof( float ) * 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, sizeof( float ) * 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
{ 0, sizeof( float ) * 6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, sizeof( float ) * 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 },
{ 0, sizeof( float ) * 15, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 },
D3DDECL_END()
};
LPD3DXMESH temp;
if ( FAILED( pMesh->CloneMesh( D3DXMESH_MANAGED, elements, pDevice, &temp ) ) )
{
pMesh = NULL;
return;
}
pMesh->Release();
pMesh = temp;
void* pData;
pMesh->LockVertexBuffer(D3DLOCK_DISCARD, &pData);
pMesh->UnlockVertexBuffer();
D3DXComputeTangentFrame(pMesh, 0);




What goes on here is quite simple. You create a new vertex format for your mesh since you want the mesh to have available space for the information you are about to calculate and store in it. You then just clone the mesh with the new vertex format and calculate the Tangent/BiNormal information using D3DXComputeTangentFrame().

Other than that. I cannot really see anything else wrong.

I hope this helps buddy.
Take care.

Share this post


Link to post
Share on other sites
First, thank you very much for looking through my code and helping me out, I really appreciate it. The extra code you supplied worked very with one exception... the object was being lit properly, but the texture was shading in the wrong direction. For example, if I moved the light to the right, the texture would shade as if the light was moved toward the camera, even though the object was actually being lit properly. Basically the X and Z positions getting to the pixel shader were switched. Here is a screen of it:

http://www.equalmeans.net/~chriss/Normals.jpg

Anyways, I switched a piece of code in your shader from:

float3x3 TBNMatrix = float3x3(IN.tangent, IN.binormal , IN.normal);
to
float3x3 TBNMatrix = float3x3(IN.binormal, IN.tangent , IN.normal);

and it is working perfectly now. I do have one last question though, how would I go about adding some ambient light to this so the back of the object isn't black, and switch the color of the light?

Thank you again very much for your help,
Chris

[Edited by - bengaltgrs on September 10, 2005 4:43:10 AM]

Share this post


Link to post
Share on other sites
Hi Bengaltgrs,
How are you doing?

The Problem
Adding ambient light

The Solution
It's very simple, simpler than you think
In the pixel shader. Just add this line to the bottom of your pixel shader.
OUT.color.rgb += 0.1f;
This will add a 0.1f ambient color to each of the red/green/blue components :)

Take care bud. Have fun.

Share this post


Link to post
Share on other sites
I see, it seems that adding the "OUT.color.rgb += 0.1f;" to the pixel shader just lightens everything, so the black areas just turn grey, and the texture does not show through at all. So instead I added this:

//find attenuation * color
float AttCol = IN.att * color;

//add the diffuse and ambient lighting
OUT.color = (AttCol * diffuse) + (AttCol * 0.2f);

This way, even the darkest parts of the mesh will always show some texture. The only thing I do not know how to do is change the color of the light. Say I wanted the object to have an orange fire-like tint to it, how would I go about doing that?

Thanks again,
Chris

Share this post


Link to post
Share on other sites
The lighting equations are well defined in the DirectX documentation as well as in the OpenGL documentation. The terms you're looking for is typically something like:


sceneColors = { sceneAmbient };
lightColors = { lightAmbient, lightDiffuse, lightSpecular };
materialColors = { materialAmbient, materialDiffuse, materialSpecular, materialEmissive, specularPower };
textureColor = { read from texture };
attenuation = { calculate based on light-object distance };
diffuseContribution = { clamp( N dot L, 0, 1 ) };
specularContribution = { clamp( reflect( E, N ) dot L, 0, 1 ) };

outputColor =
(materialEmissive +
sceneAmbient +
(materialAmbient*lightAmbient +
materialDiffuse*lightDiffuse*diffuseContribution
)*attenuation
)*textureColor +
lightSpecular*materialSpecular*(specularContribution ** specularPower)*attenuation
;


E is the unit vector from object to eye; L is the unit vector from object to light; N is the normal (which you typically get from the normal map and translate into object or world space).

Last, you don't necessarily need to send all of normal, binormal and tangent to the shader; you can send two of them, and re-construct the third using a cross product. May save some bandwidth, depending on your specific geometry.


Edit: forgot to add scene ambient.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!