PNG colour depth

Hey folks,

I’m working with playcanvas-spine, perhaps naively assuming that a 24bit PNG uploaded will remain 24bit inside of playcanvas…

I have a sprite with a nice semi transparent gradient which is part of a spine atlas. This atlas is uploaded as 24bit, but when inside of the editor, the texture ‘depth’ property is 8bit. The texture looks fine in the editor thumbnails, but when rendered, is clearly a lower number of colour bits.

Any facts as to where I’m going wrong? i.e. is 24bit texture in playcanvas just not possible because of some limitation I’m unaware of? I’ve done this for years using pixi, so it can’t be a browser issue.

Any constructive comment appreciated,


Uploaded to spine editor:

At runtime via playcanvas-spine:

Going a little further with this, I think maybe playcanvas-spine is the issue… This code deals with runtime generated spine material creation (spine.js, within the playcanvas-spine demo):

slot.materials[name] = new pc.StandardMaterial();
slot.materials[name].shadingModel = pc.SPECULAR_BLINN;
slot.materials[name].diffuse = new pc.Color(0, 0, 0); // no diffuse component should be included
slot.materials[name].emissiveMap = texture;
slot.materials[name].emissiveTint = true;
slot.materials[name].emissive = new pc.Color(0, 0, 0); // use non-1 value so that shader includes emissive tint
slot.materials[name].opacityTint = true;
slot.materials[name].opacity = 0; // use non-1 value so that opacity is included
slot.materials[name].opacityMap = texture;
slot.materials[name].opacityMapChannel = "a";
slot.materials[name].depthWrite = false;
slot.materials[name].cull = pc.CULLFACE_NONE;
slot.materials[name].blendType = pc.BLEND_PREMULTIPLIED;

// override premultiplied chunk because images are already premultiplied
// however the material_opacity is not premultiplied by slot alpha
var alphaPremul = [
    'gl_FragColor.rgb *= material_opacity;',
    'gl_FragColor.a = dAlpha;'
  slot.materials[name].chunks.outputAlphaPremulPS = alphaPremul;
  if (key) {
    this._materials[key] = slot.materials[name];

I’m still getting used to this level of gpu wizardry, but maybe there’s something in the premultiply causing the drop in colour depth?

If 24bit pngs are a no-no for playcanvas-spine, then that’s a fact that should be made widely known.

From a quick look on the Google, 24 bit PNGs don’t have an alpha channel hence the code in playcanvas-spine won’t work as it assumes the PNG will do. In a nutshell, it looks like it will only support 32 bit PNGs.

24bit is standard ‘high quality with transparency’ export for Photoshop, it can definitely work with RGBA - I guess the pixel mode would be fewer colours, i.e. RGBA6666 or something - your post did prompt me to play with the image ‘mode’ settings in photoshop though, but no dice. At this stage I’m thinking that we need to assume 8bit only pngs with spine

I think in a 24 bit PNG, transparency is handled in a special way without managing to use an alpha channel. Not sure how Pixi.js handles it though.

I can offer one better than that… Here’s a demo of the issue:

The Character entity is set up to render a spine asset. Just swap out the image with either 8bit or 24bit to see the issue.

Both 8 and 24bit images are exported via photoshop using ‘save for web’ dialogue, including transparency.

As far as I can see, png images are re-encoded to 8bit in the editor (the texture in the assets lists 8bit depth), and it’s only these which can be used in production? So any 24bit image gets ‘flattened’… I hope I’m wrong.

At this point I’m recommending our art team use an alternative animation tool for Playcanvas. Coupled with the above issue, when I embed a spine char with transparency in a scene (with fog), there’s an additive square around the object (corner depicted here):

I can understand this because spine’s automated material setup uses an emissive texture. This presentation just does not work in a game context. The Spine example project is also currently defunct: (launch the editor, then hit play) - which reduces my confidence in the runtime.

I think for Playcanvas most people are using traditional 3D animation or sprite sheet workflows - this makes perfect sense to me, but 2D artists love their Spine!

Stupid question, where are you getting the runtime from? The sample project or the GitHub repo? The runtime was made by @vaios so he might be able to answer any issues/questions that you have.

I think the repo one has a script which doesn’t include provision for layer sorting? The one from the demo project fixes that, so that’s the one I’ve been using.

Thanks for your help there @anon49240888, but my image is with the renderer, not the image :smiley: