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

Problem with normal mapping.

Started by riverreal Nov 14, 2016 at 4:29 PM 0 replies 2.7k views
Original Post
riverreal
riverreal

I'm trying to implement normal mapping in deferred rendering.

The tangents are generated with Assimp. It returns HasTangentsAndBitangents to true.

In this specific scene I have a bunch of plants, the statue and the rock loaded with Assimp. (.obj file)

And other simple generated geometry like spheres, boxes and planes.

I have 2 problems:

1. The Loaded models don't have correct tangents as opposed to the generated geometry. Should I be calculating the tangents manually without using Assimp?

2. Even if the tangents are correct in the generated geometry I'm getting really noisy specular with the normal maps. I tested the albedo + normal map in Unity to see if the problem was in the normal map, but it was woking as expected, nothing was wrong with it. It just gives really sharp results in my engine, really noisy. Could it be the lighting calculation that is wrong? But judging from the debug normals it seems like it's working.

Here are the normals, with and without normal map.

Without normal map, just surface normal.

7JGUD9T.png

With normal map.

KMOATkN.png

Notice how the normals in some models are completely wrong.

My shader calculation for the final normal output is:

In HLSL


float3 CalcNormal(float3 normalMap, float3 surfaceNormalW, float3 tangentW)
{
	float3 normalT = 2.0f * normalMap - 1.0f;

	float3 N = surfaceNormalW;
	float3 T = normalize(tangentW - dot(tangentW, N) * N);
	//This is why we don't need provide binormals, we can calculate it.
	float3 B = cross(N, T);

        //In case of mirroring
	if (dot(cross(N, T), B) < 0.0)
		T = T * -1.0;

	float3x3 TBN = float3x3(T, B, N);

	float3 result = mul(normalT, TBN);
	
	return result;
}
lawnjelly
lawnjelly

From my frustrating experience of getting normal mapping working I can't immediately pinpoint the problem but I would say a few pointers that helped me: :)

1) Maybe you can move the TBN transform to the vertex shader. Transform your light vector etc into tangent space in the vertex shader, then in the fragment shader you only have to dot the light vector with the normal from the normal map (this is done lots more times than the vertex shader).

2) Start by hard coding your normal from the normal map to be 0.5, 0.5, 1 (i.e. pointing straight up) that way the first obstacle is to get it looking right like this.

3) Don't worry about the mirroring part until you get non-mirrored UVs working.

4) There were lots of polarities of things (normal x, y, and z, vectors in the vertex shader) and everything had to match up exactly right and it would just work. If one thing is wrong (perhaps the tangents from assimp) it ends up a mess.

5) Use a really simple object / normal map to get it working. I used a cube with a hemisphere normal map, so I could see where the light was hitting it easily.

https://upload.wikimedia.org/wikipedia/commons/2/2e/Normal_map_example_with_scene_and_result.png

Topic Locked

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

Sign in to reply to this topic.