Is it possible to change the "z-index" of a sprite?

What I mean is, if there are multiple sprites that appeared stacked on top of eachother, can one change the ordering in which they appear at runtime?

Imagine a 3D game with a character made up of 2D sprites, who is holding a shield. When facing the camera, the shield should appear on top of the character, when facing away from the camera, the shield should be ‘blocked’ by the character.

It seems that the sprites appearance are simply determined based on the order they are created from their respective SpriteManager. So If I have a ‘BodySpriteManager’ and ‘ShieldSpriteManager’, how can I change the z-index/rendering order of the sprites?

I am looking for something like the Mesh’s AlphaIndex property, which unfortunately isn’t available for Sprites…

The only ‘hacky’ solution I can think of is to slightly offset the sprite’s X and Z coordinates, based on the direction of the character, and current rotation of the camera.

Hi again, SME… good to see you.

Umm… you might be talking about the BJS SpriteManager’s renderingGroupId property.

Take a look at this little puppy. https://www.babylonjs-playground.com/#UBXKZZ#3

Notice lines 33 and 47… the PG coder set player SM and shield SM… to different renderingGroupId values. (SM = spriteManager)

In lines 59-64… I added an interval timer which switches the _renderingGroupId_values of both SM’s… every 3 seconds.

Now, if you want to depth-change the sprites… to be BEHIND the sphere sometimes… then… hmm. Perhaps the sphere ALSO needs a renderingGroupId value… set. Not sure.

Anyway, with the use of RenderingGroups, perhaps you can design/build your own custom “depth manager”. :slight_smile:

Tell me what ya think, and also stay tuned for more/different/wiser ideas.

Hey wingnut, thanks for informing me about that renderingGroupId property. I think an issue with using that, is I can’t use it for individual sprites, only sprite managers. Because I’m working on an MMO, there can be a lot of different players/npcs on the screen at the same time, all facing in varying directions, so changing the renderingGroupId on the SpriteManager will work for some characters but not for others. And then of course there is the issue of needing some characters to be in front of the ‘3d meshes’ in the scene (trees, walls, etc.), and some characters needing to appear behind them… Seems a bit complicated haha.

Perhaps if there is not a simpler way, I’ll just create the sprite sheets in a way that they can ‘piece together’ like a jigsaw puzzle. It just means I will be more limited in my sprite designs

Yeah, I understand. Is it out-of-the-question for EACH character in the game… to have a “personal” shieldManager and playerManager… all the time? Perhaps one for weapon, too. Each player would have three spriteManagers.

Not very big sprite sheets. In fact, one sprite and one image, per manager. Actually, the player probably walks/runs, so it might have many sprites. But sword and shield manager… one image each, I suspect. No reason to animate them, except maybe when sword or shield is used in combat.

I’m not a game programmer AT ALL, so I really don’t know what I am talking about. And… I don’t know if there IS sprite-by-sprite depth-selection. I doubt it. Particles are the same way. They don’t like to be behind things and in-front-of things… when the particles are all members of the same particleSystem.

I believe this happens because… spriteManagers and particleSystems are actually similar to a groundMesh grid that has been busted-into separated grid cells (high performance “quads”). Since all particles (or all sprites)… are ACTUALLY part of the same mesh as each-other, they must have only ONE depth (per spriteManager or particleSystem). I could be wrong.

You can manually set gl_Position.z in the vertex shader to control the z order of specific sprites.

When I did this a while back, I just overrode the vertex shader the sprite manager uses (in Effect.ShadersStore), and used color.r to set a z value.

1 Like

I recently had to use a mesh instead of a sprite to get more control on it, if you’re interested here my test about UV animation: https://www.babylonjs-playground.com/#I4T59R#5

Sprites depth is based primarily on two things, and sorted in the following priority.

  • position vector3
  • index in the manager.sprites array

So index[1] will always render infront of index[0] unless index[0] is positioned infront of index[1].
However, sprites from different managers are purely sorted by position.

(renderingGroupId can be seen as a new “layer” of this sorting priority, so id 2 is always ontop of id 1, regardless of positions, etc)

What can we do`?
If we stick to using a single spriteManager,
Sort the array.
( Uncomment line #72 )
https://www.babylonjs-playground.com/#UBXKZZ#4

If you want to use multiple spriteManagers, you can as @wingnut points out use rendergroupid or as you thought about, offset the positions slightly.

1 Like