# What is tangent.w? How to know whether it's 1 or -1? tangent.w VS unity_WorldTransformParams.w?

Hi,

I am so confused about what exactly is tangent.w and unity_WorldTransformParams.w.

I am still a beginner and trying to figure out what is actually going on, after some searching:

What I know:

Tangents in Unity are represented as Vector4, with x,y,z components defining the vector, and w used to flip the binormal if needed. W stores handedness and should always be 1 or -1.

unity_WorldTransformParams is for odd-negative scale transforms. W is usually 1.0, or -1.0. If an object has odd-negative scale transforms, it means itâ€™s mirrored. Binormal of mirrored object should be flipped.

What I am confused:

Does tangent.w come with model from Maya or 3ds max, or is calculated by Unity?

If it comes with model, what does it indicate? If itâ€™s calculated by Unity, how is it calculated?

If tangent.w stores handedness, and Unity is left hand, does it mean tangent.w will be -1 if I set graphics API to OpenGL (right hand) and will be 1 if graphics API is set to Direct3D?

Some forum mentions tangent.w handles mirroring, then what is unity_WorldTransformParams used for? (Originally I thought tangent.w handles handedness and unity_WorldTransformParams handles mirroring.)

Thanks!

1 Like

The model from an external application usually comes with normals, tangents, and binormals / bitangents (depending on which terminology you subscribe to). Unity throws away the actual binormal and encode the cross direction in the tangetâ€™s w component.

You are also correct that for OpenGL and DirectX this value is inverted, but not exactly for the reason youâ€™re thinking. This comes down to what the tangent and binormal are representing; they are the direction of flow of the UVs. The tangent is the U of the UV, which for both OpenGL and DirectX is left to right (0.0 on the left, 1.0 on the right). The binormal is the V of the UV, which is different in OpenGL and DirectX. OpenGL is bottom to top, and DirectX is top to bottom. This is also where the difference in many engineâ€™s and 3d toolsâ€™ preference for â€ś+Y / -Yâ€ť normal maps comes from. Unity is +Y, which is the OpenGL standard, and Unreal is -Y, which is the DirectX standard. Obviously Unity is using DirectX on Windows, so most of the time the w component is going to be negative. However what if the texture UVs are inverted, not because the mesh scale is inverted, but because the meshâ€™s UVs themselves are going the opposite direction life if the textures are mirrored, then it also needs the w inverted for the half thatâ€™s mirrored.

10 Likes

Thank you!

About â€śUnity throws away the actual binormal and encode the cross direction in the tangentâ€™s w component.â€ť:

Does it mean when we import model into Unity, on Windows machine (DirectX is used), tangent.w will be -1, and on macOS (OpenGL is used), tangent.w will be 1?

If the meshâ€™s U of UV is going to the opposite direction (mesh has negative scale on the X direction), tangent is inverted. That means cross product binormal should be flipped too. In this situation, unity_WorldTransformParams.w will be -1.

If the meshâ€™s V of UV is going to the opposite direction (mesh has negative scale on the Z direction), binormal should be flipped and unity_WorldTransformParams.w will also be -1.

Other than that, unity_WorldTransformParams.w will be +1.

Am I understanding this correctly?

I guess what I am saying here is wrong? It should be tangent.w who is handling this, instead of unity_WorldTransformParams.w?

Then what is unity_WorldTransformParams.w used for?

No, as best I can tell, the on disk mesh data is stored as if itâ€™s for OpenGL, regardless of what the final platform is. The tangent.w or the unity_WorldTransformParams.w is then flipped depending on the platform, not sure which to be honest.

The unity_WorldTransformParams.w is a constant value of +1.0 for an entire mesh, it flips to -1.0 for the entire mesh if it is scaled so that an odd number of scale components are negative (like your example of a negative scale on X). The mesh doesnâ€™t need to be scaled for the UVs to be going in the opposite direction, which is why that flip is stored in the tangentâ€™s w component, the mapping of the UVs is completely arbitrary and up to the content creator.

For example this is a single mesh with no scaling (1,1,1).

Top right has a tangent.w of -1.0, as does the bottom left, where as the top left and bottom right are +1.0. However the unity_WorldTransformParams.w is +1.0 for everything.

4 Likes

Now I understand! Thank you so much!!

Now that youâ€™re no longer confused. An extra bit to throw your brain under the bus â€¦ Unity doesnâ€™t flip the texture coordinates on the mesh when rendering in OpenGL vs DirectX, it flips the textures when theyâ€™re uploaded to the GPU!

5 Likes

Does it mean in this line of code:

half3 normalTangent = UnpackScaleNormal(tex2D(_NormalMap, texcoords.xy), _NormalScale);

NormalMap is flipped upside down on DirectX platform?

And tangent.w is only used for flipping vertex normal and the texture flipping you mentioned is for normal map flipping?

Not just normal maps, all textures, but it has the side effect of solving the issue of UV and binormal differences between platforms.

3 Likes

One more question:)

How does Unity know which uv is flipped and which is not? Is the mirroring property of UVs originally stored in the tangent.w?

To a degree it depends on how your mesh was exported, and your import settings, but the basic answer is it knows from the normals, tangents and binormals in the mesh itâ€™s importing. The longer, and perhaps simpler answer, is it knows the same way you know when you look at the above image, but looking at the direction the texture (or more specifically the UVs) is going. Thereâ€™s an expected handedness to the UV â€śflowâ€ť, and if it doesnâ€™t match that orientation then itâ€™s mirrored on one axis or the other, and which axis doesnâ€™t actually matter.

4 Likes

Thank you! bgolus!!

How does unity handle the tangent.w when using static batch? I find that the binormal is wrong in a odd-negative scale object. I use unity 2018

I believe the fix for this is to stop using Unity 2018 because I think this bug got fixed in 2019.