Jump to content
  • Advertisement
Sign in to follow this  

Incorrect tangent basis on UV seams

This topic is 701 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

[SOLVED] Look below for solution.



I usually try to solve my problems on my own, as long as I'm making progress and don't hit the wall, but today I hit the wall. I spend ~20 hours trying to figure why tangents on my model which appears fine in Unity and Blender internal renderer are incorrect in my engine, and I'm lost. This is when I need to call upon powers of collective know-how and ask you for help, maybe someone knows enough on this topic or had this problem to help me figure out what is wrong. 


PROBLEM: Wherever there is UV seam in my mesh, like on head or where arms connect to body, there is a wrong lighting due to incorrect tangent basis. 


This is how the mesh looks with TBN vectors visualised:




You can clearly see that there is a seam through the top of the head where tangent basis is basically pointing in opposite direction. This is where the UV seam is too. I get these tangents from Blender itself, and it calculates them based on this UV map:




Now, I read a lot about how there _will_ be problem with tangents on the UV map seam, but I can't understand how Blender, using it's own internal renderer based on GLSL is able to get this render correctly, using material with the same normal texture, set to tangent space:




So I'm pretty sure the error is somewhere between Blender's structure representation and my exporter code. I have no idea how Blender uses these tangents it generates, I digged their shader code and even replicated it in my shaders just to be sure - but problem is the same, big lighting difference on the seam. How this is usually handled? When I export, I have 2 vertices that lie on the seam line that have 2 different attributes - uv & tangent. What I do when exporting is - check whether vertex is the same comparing all attributes, and if not, replicate it with these attributes that differ, in this case UV & tangent. This means I get 2 vertices on the same spot, having opposite tangents, and that's where this sharp line comes from.


I tried everything, best result I got by averaging these two tangents that collide on the seam vertices. But just normal average (tang1+tang2)*0.5 isn't flawless and definitely doesn't even come close to how Blender renders this mesh. This is what I get by averaging this tangent:




So there is no sharp line dividing 2 tangent basis, but it blends a bit - still looks weird, like the head is bent to the inside a bit, and the lighting "moves" in a weird way when I rotate object.


I could understand if Blender had the same problem, but it's internal render somehow copes with this, while my engine breaks :(


One more thing is that when visualizing per pixel normals, it looks like the problem not only applies to seams where it's most visible, but it also turns around the lighting on certain parts of the body:




You can see how right leg has totally different orientation of normals compared to whole back side of the model. This is due to tangent basis flowing in opposite direction there. I found that this may happen on mirrored models, but I have no idea how to fix this, is this a problem of model? Or how I export the mesh? Or Blender? And questions remains - why Blender renders correctly, if this model is wrong? 



I will be _eternally_ grateful if someone figures this out and gives me some tips pointing me in the right direction, as any following hour I spend on this just doesn't move at all towards any solution.

Edited by noizex

Share this post

Link to post
Share on other sites

Okay. Looks like the moment when you decide to write about your problem often happens just before you have that "eureka" moment and find the solution by yourself. So, for the sake of documentary and other people who might do this stupid thing too, I will let you know what the hell was wrong. It wasn't this tangent basis, turns out it works well the way it is on these screenshots.


The problem.






Texture image for normal map loaded as sRGB. Turns out I had a line that set internal format of every loaded texture to sRGB (used it for testing once), so all my normal maps were sRGB too. Found it an hour after posting, while I desperately played with Blender cycles renderer and managed to reproduce exatly the same error as I had using a "color" node. Turned out setting it to "non-color data" fixed the problem in Blender, and after checking what this means, turned out it's Blender's way to tell it that you want color data and it treats it as sRGB. 


So make sure your texture is in correct format when you have weird artifacts like this on UV seams. Can't even think how much time I wasted looking at my exporter, fixing shaders and pulling my hair out. And it was a single, tiny line in a code I didn't even look into.

Edited by noizex

Share this post

Link to post
Share on other sites

In your per pixel normals visualization, is that the normal sourced from the vertex data, or the normal sourced from the normal map (and decoded using the TBN matrix)?

What does the normal map for the head look like? Does blender use the same normal map as the game?

Do you have any way of validating that your game is using the same per-vertex tangents/bitangents as blender?

Do you export/import the tangents and bitangents (aka binormals) from blender into your game, or do you only export/import the tangents?



Texture image for normal map loaded as SRGB.

Oh god... Congrats on finding that :D

Edited by Hodgman

Share this post

Link to post
Share on other sites

I had similar problems getting it working, and it turned out to be as simple as a colour channel needed flipping in the normal map. sRGB must have been even more tricky though!  :lol:


I also had issues calculating the tangents on the seams of mirrored UVs. But it looks like you are letting blender do that for you.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!