[SOLVED] Color space of textures

Hello. I’ve been using PlayCanvas for many years now, and one thing that always bothers me is how PlayCanvas handles texture color spaces. In a “standard” PBR shader, color textures (Diffuse, Emissive, Specular) are interpreted as being in sRGB color space (i.e. Gamma corrected), while data textures (Metalness, Glossiness, AO, etc.) are interpreted as being in Linear space (i.e. not gamma corrected). I’m not sure PlayCanvas handles data textures correctly? To me it looks like they always end up too bright, as if they too are being de-gamma’d by the shader.

I just made some examples comparing many renderers. First, let’s look at the source material in Substance Painter:

Compared to how it looks when imported into Playcanvas:

The glossiness is way off. If I manually apply an inverse gamma correction to the Glossiness texture in Photoshop (Image > Adjustments > Exposure > Gamma Correction > 0,4545), the material looks much closer to the source:

Here are some other renderers using the source textures from painter as-is:

I also exported a glTF file from Painter and compared how it looks in BabylonJS’ viewer and PlayCanvas’ viewer:

As you can see, even the PlayCanvas glTF viewer is closer to the source than PlayCanvas’ own editor/engine.

Why does this matter? Well, when working with texture creation programs such as Substance Painter, you want to be able to see the final result, and not get an entirely different result when importing to the render/game engine. You also want to be able to reuse textures between different engines. And as we can see from the examples, the odd one out here is PlayCanvas. Right now we have to author textures specifically for PlayCanvas, which is a pain.

I’m not a shader programmer, but I glanced over the source code of the shader chunks. I can see that diffuse textures are being de-gamma’d using gammaCorrectInput and that Glossiness textures aren’t. From what I understand, this is the correct way to handle color spaces. So how can it look so wrong?

1 Like

Calling @mvaligursky @slimbuck

Hi @Sidelity,

We’ve actually noticed a discrepancy with glossiness sometimes and for us it’s also a big deal!

Really interesting that applying inverse gamma appears to fix the levels.

This is definitely worth investigating… any chance you can send us your model for testing? I actually think it’s worth creating an issue on github for this.



Oh wait, I didn’t pick up on the fact the model looks different in the editor compared to the viewer.

That really is interesting, because both use the same engine (but different asset pipelines).

1 Like

If possible, I’d love to get the FBX file and the glTF you’ve created so I can compare them locally.


Absolutely, here’s the FBX with the associated textures, a packed GLB, and the source Substance Painter file.

Also, here’s the PlayCanvas project I’ve used:

Thanks for looking into this!


If you create a GitHub issue for this, mind posting the link so we can follow its progress?

Sure, done!

Ok I’ve found the issue.

We updated our IBL implementation a few months ago in this PR. One of the changes was to generate blurry reflections using GGX lobe (which is industry standard) instead of our old phong lobe.

The PlayCanvas model-viewer uses the GGX lighting environment, but the editor was never updated to use it. This is actually a known issue (though tbh I actually didn’t fully appreciate just how big the difference is in some cases) and will be fixed real soon.

I actually forked your project and added code to switch between the standard editor lighting and the new GGX-generated lighting. Check the difference in this project.

Sorry for the trouble on this one. It shouldn’t be much work on our side to update the editor, so I’ll try get this done soon as possible.



Great job finding the issue.

How will this fix affect previous projects, where materials are created for the old Phong lobe? Wouldn’t they end up looking too rough when using GGX?

Wouldn’t they end up looking too rough when using GGX?

Yes, most likely. I haven’t discussed with the team yet, but we’ll probably add an option so users can still use the old phong lobe.

Though tbh I am quite keen to get rid of the old phong support entirely. Not only is it non-standard, but the resulting blurry reflections are much more noisy, especially under high contrast lighting conditions. So we’ll likely flag it as deprecated and remove it in future.

Cool. As long as the change isn’t forced, I’m happy. That would allow us to “migrate” each project separetely when we have time. We have many customer projects that we maintain, some with hundreds of glossiness textures each, so the idea of recreating them in one go isn’t all that fun :wink:

1 Like

Hi @Sidelity,

This has been released.


1 Like

Hi Guys,

It seems this issue is not resolved. I compare my GLB in the editor and the viewer and the editor is applying gamma correction to the specular and glossiness textures. That’s incorrect. To combat that, I have to apply inverse gamma to the source textures (maybe losing some data), then upload to the editor project, so the values are read as linear in the editor.

There is also some odd light source in the editor when you turn off the light and set the HDR exposure as low as possible.

Hi @Matterfield - are you able to create a simple repro for this and create an issue here please: Issues · playcanvas/engine · GitHub

Will do. Thank you! Great work on this toolset btw. Very impressive.