Texture changes in PlayCanvas

We will be releasing an update to the PlayCanvas Engine which requires textures to be recompressed.


When the PlayCanvas Engine was created many years ago, it adopted the convention that textures have their origin at the bottom left of the texture. This is the standard used by OpenGL and many modelling tools like Blender and Maya.

However WebGL and glTF adopted a different standard and consider a texture’s origin to be top left.

Up until now this has meant the PlayCanvas Engine must flip textures vertically at load time in order to render correctly. Since it is not possible to flip compressed textures at load time, the PlayCanvas backend has been creating vertically flipped textures instead.

We are now working on an update to the Engine which will make it consistent with WebGL and glTF. This will simplify the engine going forward and in some cases speed up load times.

Editor impact

This means that existing projects containing compressed textures must be re-compressed otherwise textures will appear upside down.

We will be adding a popup message to the Editor and single button to recompress all textures in a project. See below for a mock up:

This should make the transition reasonably straightforward for you. You simply have to wait for all textures to recompress (and that time will depend on how much compressed texture data exists in your project).

Engine impact

If you generate UV coordinates at runtime you will have to ensure texture V coordinates are correctly flipped. For example you can add the following to your shader:

texCoord.y = 1.0 - texCoord.y;

This also applies to custom shader chunks. Specifically, if you have custom versions of the following chunks, you will need to ensure the V coordinates are correctly flipped:

  • particle.frag
  • particle_cpu.vert
  • particle_normalMap.frag
  • startNineSliced.frag
  • startNiceSlicedTiled.frag.

Release Date

We intend to deploy this update on Monday 19th July. Please let us know ASAP if you have any concerns or questions.


To check progress when you re-compress the textures, you can filter the assets panel by Texture type and put a . in the search bar.

This will list all the textures in the project and can check if textures are still compression by the loading bar or spinning icon:

1 Like

This has now been released :rocket:


For custom shaders using the standard texture coordinates, simply doing this resolves any texture flipping:

vec2 uv = vec2($UV.x, 1.0 - $UV.y);

I’m gonna guess this is why my game now looks like this? :slight_smile:

For a refresher, I use texture packer → texture atlases with batching. Havent touched the project in a while but making some improvements atm.

Edit: I should point out things look correct in the editor, but not when I debug/play.


Can you re-add me/link me to the project again please and I will take a look. It’s odd that it looks fine in the Editor but not when you play :thinking:

1 Like

unfortunately i think there is a bug in legacy compress on alpha textures.To represent the issue here is a link of demo project:

Basis compression is normal but legacy dxt compressed alpha image has black background.You can see this in the project link

Hi @esr_esr,

This should now be fixed. Please recompress your DXT.

Sorry for the trouble!

1 Like

Thanks for the quick fix Slimbuck

I’m confused. Are you sure you don’t flip uv1.y on glb models? I have made a test scene where I load an fbx. I have verified this fbx in blender and by manually loading the fbx to have uv1.y coordinates going from bottom=0 to top=1. But in my public test scene (https://playcanvas.com/editor/scene/1197454) the uv1.y coords go from top=0 to bottom=1. I dump the coords in the console, and the shader sets color directly from uv1.y, which makes it white at the bottom, black in the top.

Applying a texture does give expected result, so I’m only wondering about the actual uv.y values.

I would prefer that uv coords are not changed from what they are in the source mesh (fbx), as uv coordinates can be used for many things besides texture lookup.

I got the same output in vegetation geometry that uses texture coordinates to simulate wind (no texture used). I had to flip those coordinates on the y axis to get them to work with v1.45.0

Yes, but that would be compensating for PC flipping the uv.y, which is not ideal going forward

1 Like

@slimbuck what do you think?

Hi @Snupty,

Yes it’s a bit confusing, I will attempt to explain.

Maya and Blender and OpenGL consider the uv origin (0,0) to be bottom left of the texture. (This also means the first byte in GPU texture memory is the bottom left of the image).

However WebGL and glTF decided instead to specify uv origin (0,0) to be top left (see for example the glTF spec and WebGL spec - “The first pixel transferred from the source to the WebGL implementation corresponds to the upper left corner of the source”).

This means some conversion is necessary between Maya/Blender/OpenGL and WebGL/glTF.

There are two options to accomplish this:

  1. keep model texture coordinates as they are and flip all textures vertically
  2. transform model texture coordinates using: v = 1.0 - v and keep textures as they are

The issue with flipping textures at load time is that this is not possible when dealing with compressed textures. Compressed textures must be flipped at compression time instead.

Therefore the standard approach taken by the industry is to keep textures naturally orientated and invert texture coordinates instead. All glTF converters and viewers expect this.

In v1.45.0 of the engine we made a number of changes in this area and now store texture coordinates as native glTF and we store textures naturally oriented. (The engine was flipping glTF texture coordinates -and- images at load time before).

The engine change means we can now more easily handle things like vertex quantisation and texture coordinate transforms correctly and will simplify the pipeline going forward. However as you’ve seen, it can impact things like custom chunks.

I hope that makes some sense :slight_smile: Let us know if there’s anything else we can do to help!


Hm, wouldn’t it be better then to change your own shaders to invert the v-coordinate when doing texture lookups? I don’t like that you change the vertex data. Also, what you’re telling me is contrary to what another PC team member told me earlier, “Before this release, when a glb was loaded, we had to loop over uv coordinates of the meshes and do v=1-v. Now we don’t have to do this at all.”

Just a funny observation. Looks like the icons in the editor were flipped by this change:

1 Like

@Snupty - have a look at the changes in the PR: [FIX] Adopt top-left texture origin by slimbuck · Pull Request #3335 · playcanvas/engine · GitHub
in the glb-parser, we stopped flipping V coordinate
and in json-model we started flipping them

But now they are flipped compared to the given vertex data. So when I set it v=0 on the model it comes over as v=1. I don’t know where this happens, maybe it’s during fbx to glb conversion then.

Hi @Snupty,

Yes the FBX->glTF converter performs the V flip in order to conform to glTF standard.

1 Like