engine icon indicating copy to clipboard operation
engine copied to clipboard

Detail map normals and material normals are combined wrong when using different UV channels

Open animech-sijo opened this issue 1 year ago • 1 comments

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: Toggle

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): Comparison

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: FlightHelmet_Toggle

Tested on both Firefox and Edge, and using the latest engine version as well as older ones.

animech-sijo avatar Jan 25 '24 13:01 animech-sijo

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).

aidinabedi avatar Feb 06 '24 21:02 aidinabedi