In other news, so why did I spend time getting texture loading and sprite code working in my engine?
A sudden mad impulse to clone After Burner, that's why!
The code is all ugly and hacked up, much like my pixel art, but basically, yeah. We can create rows upon rows of axis-aligned billboard sprites with various textures, and scroll them around and whatnot. Getting it all working was absolutely trivial. The only even remotely tricky bit has to do with the intersection between depth testing and transparency -- normally, it's a huge hassle to properly depth sort transparent objects, and you end up having to manually sort them from farthest to nearest and draw them in order. The problem with that is that the most expensive thing to do on today's 3D cards is context switching -- changing from one texture to another, for example. If I was drawing all that ground clutter in order from farthest to nearest, I'd be constantly switching from one texture to another.* Fortunately, there's a cheat. If your objects are either 0% or 100% transparent, as Sega System II-style sprites are, you can set glAlphaFunc(GL_GREATER, 0.1); and OpenGL will do the right thing. It's a limited solution, useless in the case of translucent objects, but for what I want to do it's perfect.
I did experiment with using point sprites, which would be even faster as they do the billboarding for you. Unfortunately they are effectively limited to 63 pixels across which is, you know, not a lot. Manually billboarding the sprites is much slower, but I suppose it'll be good enough. If it genuinely becomes a problem (and in the unlikely assumption this project goes anywhere) I'm sure I can move the billboarding into a shader and speed things up quite a bit.
* To be sure there's plenty of other ways to address this, such as having one big texture with lots of little images in it, or using multiple texture channels. But I didn't feel like getting cute just at the moment.