Sorting Alpha Blended Sprites

I have been tinkering with alpha blended sprites for projectiles instead of additive blending, and Q3 doesn’t seem to sort them by depth. If I fire off a bunch of projectiles in a line it looks correct at first, but if I do a cg_thirdperson 1, cg_thirdpersonangle 180, cg_thirdpersonrange 2000 so that I’m firing toward the camera, the sprites seem to be sorted backwards, with the farthest ones rendering over top of the closest ones to the camera. From what I can tell it appears Q3 is sorting the sprites by entitynum when it runs the scene render. If a projectile impacts something and the entitynum gets recycled out of numerical order one sprite will render out-of-step with the others. This happens both in normal Q3 and in IOQ3.

Here’s a shot of what it looks like from the player’s POV:

Here’s the problem:

I’ve tried changing the depthfunc and using depthwrite but they cause bad results. I’m not super versed on how the drawsurf sort routine works so does anyone have any ideas on this one?

Surfaces are sorted by order added to scene, shader load order, and shader sort value (opaque, transparent, …) which is automatically set for blended alpha (blendfunc blend). Quake 3 does not support distance sorting. As far as I know, in Quake 3 there is no good way to handle blended shader overlapping other blended shaders.

For fixed level geometry there is a few shader sort keyword values that can work around it. (Shader sort is actually a decimal, so as long as order in-game is fixed, shaders can be forced to sort correctly.)

For just plasma sprites, I suppose CGame could manually make a list and sort them by distance and run trap_R_AddRefentToScene() in the correct order.

This could be done using drawsurf sorting as well which would ensure it’s also sorted correct in mirrors/portals. It may be useful to sort render entities by distance for each scene and use ‘sorted entitynum’ in drawsurf sort key instead of adding depth to drawsurf sort key which runs into how many bits do you want to spend on distance value. If I remember correctly Quake 3 is already using almost all of the 32-bits available for the sort key used by it’s sort method. Though Spearmint supports 64-bit sort key.

That cgame suggestion is actually a good idea. I’ll give that a try and test it against mirrors as well. Thanks!