Baked normal map artifacts - tangent discrepancies?


We recently came across a problem regarding baked normal maps from Substance Painter imported into Playcanvas. Here’s our setup:

We import these models into Substance Painter, and bake the normal map. The result looks something like this:

When we import the same model and normal map into other engines, we get a good result. We tried Unity, Unreal, and Blender 2.8’s Eevee. Here’s a screenshot from Unity:

Looks OK. However, when we import the normal map and the model into playcanvas, it looks like this:

According to this video, by the Substance team, when baking normal maps in Painter we need to keep in mind how the target game engine handles tangents. Unreal, Blender (and Unity 5.3beta5 and up) uses MikkTSpace to calculate tangents. Substance Painter also uses MikkTSpace. Therefore, it is considered a synched workflow, meaning we don’t need to export tangents from the 3d package.

If the target engine doesn’t use MikkTSpace, we need to export tangents with the model from the 3d package. These tangents are then used in both Substance Painter and the engine.

We did not see any difference when trying the two methods above, leading us to think that Playcanvas always calculates its own tangents. But it doesn’t seem like it’s using MikkT?

If somebody could shed some light on this issue, it would be greatly appreciated. As it stands now, we cannot get Playcanvas to produce the results we want.

Here’s a project showing the problem in Playcanvas. Feel free to fork, and also to download the assets to try in different game engines:


Ping @dave @will , can you take a look at this?

I do wonder if this has anything to do with it:

BTW, it doesn’t matter if you export your FBX with or without tangents. PlayCanvas will never import them. So that’s why both your imported models in the scene look the same.

I don’t have any more info for the moment without a bit of investigation…

I’m having a bit of trouble following what’s going on in that github issue - I’m just a simple artist :wink:

Derivative maps was proposed, but then something else is committed that fixes the issue that derivative maps was supposed to fix. Am I understanding it correctly? Or was derivative maps actually implemented?

What I’m interested in at the end of the day: how does playcanvas expect baked normal maps to be generated?