[SOLVED] Normal map. OpenGL or DirectX?


I’m exporting textures from Substance painter. Aiming to do a PBR metal roughness material. For the normal map, I have the choice of DirectX or OpenGL. What type does playcanvas assume/prefer?


  • Björn

What is the difference when you chose one or the other in Substance painter?
If texture is saved as TGA or PNG or JPEG, basically non-GPU compression formats, then actually there is no such thing as PNG for DX or GL. This is something unique to Substance painter.

Exactly, I tried both now. And DirectX looks like crap but openGL looks just like the substance viewport. So I guess I have my answer :slight_smile:

1 Like

On the same note. Playcanvas wants Metalness + glossiness rather than Metalness + rougness, am I right?

glossiness = 1 - roughness

Great, so I’ve set up this little template for playcanvas export from Substance painter.

I would recommend combining Glossiness, Metaliness, Ambient Occlusion and Height into one texture with each channel per type of texture. Or any other combination you feel there is a fit.
There is a pattern in Editor, we do recognize certain types of postfixes on textures, for example: gmao - when you apply such texture on empty slot in material, it will auto-bind: gloss, metaliness, ambient, opacity - automatically.
It is good practice to reduce number of textures, saving VRAM and reducing download size.

As well, use Ambient Occlusion on models, it makes big difference: https://developer.playcanvas.com/en/user-manual/graphics/lighting/ambient-occlusion/

Oh wow, that’s genius! So just to recap. I set it up like this, and the gmao-suffixed texture will represent 4 textures in on RGBA texture?

I guess a black and white texture is smaller than an RGBA though, so will this really save much?

JPEG does not have black and white colorspace formats. And PNG does but in GPU it is still RGB8 or RGBA8.
So yes, it makes huge difference, plus instead of 4 network requests you get only one, which makes big difference on loading times for high-latency cases (when your server is far from user).

And for Normals, you usually want them as PNG, and it makes sense then to put Heightmap into A channel, to save VRAM and another network request again.

So many great optimization tips, THANK you Max!

But PNGs for everything is not a great idea then?

I actually prefer TGA’s :slight_smile:
When you upload TGA, if it has no alpha channel, it will result in JPG, but when you add compression to it, it will make compressed textures from original TGA, which won’t double the compression artifacts (when done from JPEG without TGA source).
If TGA has alpha, then it results in PNG. For normals and glossiness I do recommend PNG, for the rest JPEG is fine most of the time.

If I wanted to combine Normals + Height into a RGBA TGA that transforms into a PNG map then, what suffix would I have to use in order for playcanvas to pick it up correctly?

Btw, I did a RGBA _gmao texture in TGA but it got converted to a JPG in playcanvas and I’m not getting the automatic assignment of channels anymore.

There is no prefix for this case, just manually apply same texture on normals and height, and choose channel for heightmap.

When uploaded, it should convert it to PNG in same folder. Which if you apply on empty slot, will do auto binding. Although you can manually set same texture on different slots and don’t forget to choose right color channels by the slots.

Cool. I wasn’t aware of the manual channel setting. However, my TGA does turn into a JPG, not a PNG.


Hey, thanks for this. Very helpful!
Quick question…How are you changing the texture settings in Substance to be Metal / Gloss, rather than Metal / Rough (which is the template)? Or are you just inverting the roughness map once it’s been generated?

There are options for exporting gloss maps from Substance. Just go into the “Export document configuration” settings:

I’m almost done with this project, but it ended up at 120 MB. Seems kind of hefty, and I would love to get it down. Most textures as done like you suggested @max,

  1. One JPG for Diffuse
  2. One PNG for GMAO
  3. One PNG for Normal.

Most of them are 2048x2048 and I have 7 materials. That is 21 textures in total. The PNG’s weigh in on around 2-3 MB but I’ve also added all the compression flags like so:

See any low hanging fruits for optimizing size/download speed?


  • Björn