engine
engine copied to clipboard
Detail map normals and material normals are combined wrong when using different UV channels
If we have a material using a normal texture in UV 0, then apply a baked normal map as detail in UV 1, then we get wrong normals as a result. If however the material normal and detail normal use the same UV channel, we get correct results. When toggling the material normal UV channel it looks like this:
In this example, the normal texture in the material is a solid color, flat normal (127, 127, 255), so it shouldn't affect the end result.
If we swap the textures so that the baked normal map is in the material, and the flat normal map is applied as a detail, we get the correct normals no matter what UV channel configuration. Here's a comparison of the different combinations (the top left is wrong, the rest is correct):
The example project can be found here:
https://playcanvas.com/project/1184651
Try toggling the material TestObj
's normal UV channel. When set to UV 0, we get wrong normals. When set to UV 1, we get correct normals. The expected result is that there shouldn't be a visual change when using different UV channels.
While the example project may not look that wrong, it's very visible when working on real models:
Tested on both Firefox and Edge, and using the latest engine version as well as older ones.
Just wanted to let you (PlayCanvas devs) know, that we've isolated the issue and developed a workaround.
The root cause is the algorithm used to compute tangents in the standard material shader (i.e. TBNderivative.js
). Since the computation depends on which UV channel the normalMap uses, the tangent can change handedness if the normalMapUVs are say mirrored. This may be fine for the regular normalMap but is problematic for a normalDetailMap that can use an independent UV channel. I've also noted that there is a TODO in the engine that seems to highlight this problem.
The best solution is, of course, to have pre-computed tangents, but unfortunately, the editor doesn't seem to keep tangents when importing models (at least not for fbx or glb).