I’m going to write a plugin for xNormal, which should calculate exactly the same tangent basis as in Unity, so the pixel shader and the normal map generated in xNormal would match pixel-by-pixel perfectly. For this I need to know, which approach do the Unity devs use to calculate tangent basis.
I don’t expect that you (Unity devs) provide some excerpts from the source code here but I would be thankful for some support
I found some articles about tangent base calculation but which of them applies for Unity?
Can you store tangents in the model before Unity imports it? Presumably Xnormal uses stored tangents as well (unless you override them). This would guarantee that both Unity and Xnormal were using the same tangent space basis.
That’s not really the issue, the normal map need to be calculated with the same tangent basis that unity’s render uses for the normal map to display correctly, making sure the mesh’s are identical is not the issue here.
Unless I’m missing something, the information in the mesh is exactly the issue. Here’s how Unity computes the tangent space basis in its vertex shaders:
As you can see, it uses the normals and tangents stored in the mesh in a pretty straightforward way. If you supply meshes with tangents and normals, then the tangent space basis should be the same for both Unity and Xnormal.
The only problem would be if you’re letting Unity generate tangents and normals for you. In that case, knowing the method it uses is crucial to getting good results from Xnormal.
It would be GREAT if UT would write a plugin for xnormal so that there is a proper way of generating normals for use in Unity.
This whole thing about having to go all kinds of hoops and loops (assigning lots of smoothing groups, splitting the UVs at harsh bends and so forth) is a pretty big showstopper.
Does anyone know what the actual issue is? I explained above how Unity computes the tangent space basis from mesh data. Does xNormal use a different method?
I think they’re asking how to calculate the same thing Unity does when ModelImporterTangentSpaceMode is set to calculate. This is a different problem than calculating the rotation matrix in the shader.
That assumes the 3D app supports their export, as does the model format being used (which I think would eliminate OBJ, for instance). In short, I agree with you that that’s the best approach, might not be an option though.
@Daniel; My grief with the way Unity currently handles normalmaps i that you have to do all sorts of tricks to get the normal map to display correctly.
A simple example would be how you normal map a box. Currently the only way I can display a normal mapped box without weird shading is to have several different smoothing groups and to have the UVs split wherever I have a new smoothing group. Even with this setup I actually get small seams along all edges although not very visible when the diffuse has been applied. Still its a pain in my artist eye
In some other engines such as Marmorset or CryEngine it is not necessary to split up the UVs and the mesh in seperate smoothing groups. Simply apply one smoothing group and keep it in one single UV isle. Marmorset can display the normals you generate in max straight out the box whereas CryEngine supports normal maps created using their own baker.
What Marmorset and CryEngine does is much preferred. You do not need to add unneeded geometry or to split your UVs and smoothing groups. This is good both for performance and for memory use. Also for the artist for whom its a pain to paint textures if the UVs are split up in too many isles.
From my understanding its a matter of how engines interprets the generated normal maps and in theory there should be nothing keeping Unity from actually displaying normal maps in this more “correct/modern/optimized” way. From my understanding the actual problem is that there currently are no tools available to generate normals that work correctly with Unity. This is where Xnormal comes into play as you can write plugins for this program depending on how a given engine interprets normal maps. So in essence if we had a plugin for Xnormal aimed at Unity we could get much better and more efficient normal maps.
Please correct me if I am wrong. I am just a simple environment artist who doesnt really understand much of the technicalities but who indeed is slightly annoyed with the normal maps thing. It would be very interesting to get UTs input on this too because to be frank I do not understand why we have to go through these hoops to get decent normal maps working.
What mesh format are you using, and what are your import settings for normals and tangents? Where are you getting your normal maps, and how are you importing those?
FBX from 3DSMax, even when exported with tangents, screws up on Unity import and you have to tell it to calculate them.
Matching the mesh’s normal/binormal/tangent for baking to those used by the game engine when displaying a normal map is very important to get the most out of your normal map.
It almost entirely removes the need for support geometry and other hacks like UV splits and smoothing splits. Making the model more efficient and it’s creation far less fuss.
@Daniel; Well basically what Farfarer said. If we had a way to generate normal maps with the same tangent basis as Unity uses then we could display normal maps the way it should be dsiplayed (without excessive geom, UV and smoothing splits). An easy way for UT to help us create these correct normal maps would be to write a plugin for xnormal as the original post by SONB was about.
The normals and tangents of the mesh is not the issue. Mesh is imported as fbx (single smoothing group, single UV isle) and normal map is created in max or current version of xnormal (neither displays correctly in Unity).
I don’t really think I get what the problem is with the normalmaps, then.
I know FBX often does not translate Edgebreaks/Smoothgroups over too well. Farfarer said 3DS Max also has problems with it, I know Cinema 4D simply doesn’t export edgebreaks in FBX. So a Normalmap calculated by xNormal (or any other normalmapping program) takes the lowres mesh with or without edgebreaks and translates the high detail information over into the normal map. Good. So far I’m very used to the process.
A normalmap also is to some extend capable of translating harder and softer edges on a model without edgebreaks applied.
My impression was that normalmaps pretty much carry the same information and different programs simply differ in R/G/B channels inverted. The UV seams I get by viewing a model in different realtime engines. So far only worldspace normals could get rid of them.
Now what I don’t understand is … why is this a matter of How Unity treats normalmaps? Edgebreaks are more of a problem with the model than the normals in the first place.
And how is this an issue that can be fixed in the normalmap itself?
The way normal maps work is the same across all programs.
However, all programs and games have subtly different ways of generating the mesh normals for displaying the model in the viewport (and often different, high quality ones for the actual rendering when baking the model).
These differences mean that a fair bit of extra work has to go in to ensure that what looks good in the viewport of your 3D app also looks good in your game engine.
Here’s a good example of 3DS Max’s own normal discontinuity - the normals it generates for the viewport are completely different from those it generated for the model when the normal map is baked (top row). And an example image of the same baked normal map, but using normals in the viewport that are generated to be identical to those used in the render/bake (bottom row).
It’s a substantial difference and that’s just within one 3D app. You can start to see how even a small dis continuity cross-engine/cross-app can cause horrible visual issues.
Okay … but in that way it’s more of an issue that the normalmap matches the normals/edgebreaks from the model, right?
Or in other words: if the edgebreaks during the baking process match the edgebreaks in the realtime solution the result should be correct, right?
The example here is from the Cinema4D viewport. Normals baked from Topogun.
The normals have been baked into the model with no edgebreaks included in the lowres model whatsoever.
The top image shows the normalmap aplied without any edgebreaks, either.
The bottom image shows the model with edgebreaks (stadard Phong-Sngle only) active.
The result in Unity is similar: when applying the normals onto the model without calculated normals and edgebreaks it looks pretty much okay. Only as soon as the model has edgebreaks active it starts to look weird.
Granted - the edgebreaks aren’t created specifically for the object. it’s just a phong angle.
It’s only to illustrate what I mean and what I don’t understand about it.
(yeah - it’s the example from ryan kingslien’s book … you gotta start somewhere with hard surface in Zbrush, eh? )
The normal map should always match the normals and edgebreaks. The vertex normals, positions or smoothing should not be touched after the normal map is baked.
You can clearly see in that “pretty good” image (the top one) that it’s got smoothing issues all over it. So we know that Topogun and C4D do things differently.
If the normals and tangents that you baked it with were identical to the ones you display it with in the viewport/Unity - there would be no issues at all. Just like the example I posted.