Dust

The significant new update is the addition of dust and, in general, an efficient way to track particles floating through space.

It would be an easy problem, if I didn’t require the dust particles to react to external forces. Until now, the dust has all been stationary, and is obviously just a big dust cloud texture at various depths in the -z axis to provide some feedback on ship speed and apparent depth to the view.  But even having dust floating around randomly could be done pretty much exclusively in the shader- a bunch of 1×1 quads with varying Z-axis depths to provide differentiation to the vertex shader, and a uniform giving the current view coordinates.  Pretty much all the work would be done on the shader, which for my purposes makes it effectively free.

But wait, they’d eventually drift off the screen.  And since I’m not tracking the entire universe worth of dust, there wouldn’t be any more dust drifting in from far off the screen to replace it.  If the player just stood still for a few minutes, the screen would clear.  I could have the particles wrap around, but that might be noticeable.  So given a random value stored in the Z vertex and time stored in a uniform, I wrote a shader which would randomly move each particle in some direction for a while, then fade it out, then fade it back in near the original position floating in some other direction.  Since the fades in/outs are randomly distributed through all the particles, I think the trickery should be pretty transparent to the user, and look like a randomly moving cloud of dust.  If I wanted to, I could even assign nearby particles similar “random” values and reduce the amount similar values are split in the shader, to have them float in loose groups, to give the impression of currents.

So this is what I did for a while, and the results were acceptable.

But it’s a trickier problem if I want explosions to have an effect.  They have a permanent effect on particle position, there is no limit on how many there can be, and their timing is important.  It is unclear to me how to create a shader that can handle all of that without being able to store all the position and velocity data between frames.  I suspect that this might be possible with newer versions of OpenGL, but I’d rather not have significantly more demanding system requirements on a 2D game for the sake of nicer dust, and there’s far too much undone to start writing multiple render paths right now.

So the obvious answer is to track it all in C++, where all that information is available and remembering things between frames is not a problem.  Obviously, tracking all the dust in the world is ridiculous, so I’d have a chunk of memory I’d stake out on game load that I would recycle as old particles drop off the screen and new particles get added on.  It would have to extend a little beyond the edges of the screen, so an explosion near the edge wouldn’t reveal undisturbed dust if the view shifted in that direction, but still, pretty much just enough particles to fill the screen.

Each explosion triggers a search through all the particles to figure out who is nearby (since current position is unrelated to starting position, that can’t really be simplified).  Beyond that, it’s simple- add velocity*time to the position, and degrade velocity a bit.  I toyed with the idea of combining them into groups of 100 or so and setting an “untouched” flag on them, to skip all that computation if they haven’t been touched by an explosion, but since that would fail to save much effort when the computer was the busiest- lots of combat going on on screen- it seemed like a waste of time.  I can’t come up with a way to avoid having to think about every particle every frame.

So not only am I doing more work on the CPU than I envisioned when I started thinking about dust, but that shader I worked on is kind of redundant.  But perhaps there is a common solution.  I could dump the detailed background (the one not included in most updates due to size), and replace it with some drifty clouds, powered by the dust shader, only with much larger and many fewer particles.  It would give a kind of nebula effect, and positioned moderately far back in the Z axis, it would be plausible that it is not touched by explosions in the foreground.  And given the additional non-static visual complexity, maybe I could track many fewer particles in the foreground without losing the feeling of space not being boringly empty.

Or perhaps I’m rationalizing a use for the shader because I dislike cutting something that I spent time on.

In any case, I was careful to write all the dust code with a “density” variable, so it will be easy enough to stick a slider on that value and let the player reduce it if it ends up actually having a significant effect on performance when the game is completed.

This entry was posted in State of the Game. Bookmark the permalink.

Comments are closed.