I am trying to include smoke trails in my PC game, which are an alpha-blended particle effect, and I'm having problems with efficient rendering.
I'm using DirectX 9, but I suspect what I need is a new methodology or algorithm, not a change in the DirectX-specific graphics code, so I thought it best to post here (if we can't figure this out, I'll post in the DirectX forum later).
Allow me to explain how my smoke trail algorithm works. If you have a suggestion for improvement or an entirely different way of doing it (which I suspect will be the best solution), please let me know.
Smoke trails are to follow moving missiles in my game. They take a long time to die away (~20 seconds), so they will end up being quite long and may be visible in a portion of the game universe long after the missile itself is beyond view. They are relatively thin (from 4 - 15 pixels, depending on how closely one zooms in with the camera), whereas they can easily be tens (or even hundreds) of thousands of pixels long (though only up to 32,000 pixels of that length can be on-screen at once, when the camera is zoomed out to maximum).
The smoke trail is saved as an array of points. Each frame, the last point in the array is overwritten with the current missile's position. Every so often, either once the missile has traveled ~500 pixels or if the missile has turned sharply enough, the last point in the array won't be overwritten - instead, the array will be incremented to include one more point (the new "last point" is given the missile's position and is continually overwritten until the array must be expanded once more).
This array of distant points is great for describing the general trajectory of the smoke trail, but they are too far separated for rendering.
In order to render, I first determine which points are visible on the screen during the given frame. Then, for each of these points, I use the size of my particle texture and my camera zoom level, as well as the distance to the next smoke trail point, to determine how many particle textures I must render between the points to make a smooth column of smoke, the position of the first particle texture (in camera coordinates), and the separation (in camera coordinates) between particle textures that will be rendered in sequence.
For instance, let's say only two points are visible on the screen - at camera coordinates (0, 100) and (100, 100). Let's say that the particle width and height are 2. Based on the creation time of the two visible points in my smoke trail, I know I need to draw them with an alpha of 0.5 and 0.4, respectively.
Then, for rendering, I calculate the following:
vector_2d First_particle_cam_coords = (0,100);
vector_2d Final_particle_cam_coords = (100,100);
float First_particle_alpha = 0.5;
float Final_particle_alpha = 0.4;
float particle_size = 2;
int Num_particles_to_render = Length(First_particle_cam_coords, Final_particle_cam_coords) / particle_size;
vector_2d delta_position = (Final_particle_cam_coords - First_particle_cam_coords) / Num_particles_to_render;
float delta_alpha = (Final_particle_alpha - First_particle_alpha) / Num_particles_to_render;
In the actual rendering loop, I simply draw my particle texture in a for loop:
vector_2d particle_pos = First_particle_cam_coords;
float particle_alpha = First_particle_alpha;
for (int i = 0; i < Num_particles_to_render; i += 1)
particle_pos += delta_position;
particle_alpha += delta_alpha;
I've investigated my code and I've found the following:
-When several smoke trails are on the screen, the frame rate drops significantly.
-The problem is exacerbated by larger zoomouts and larger resolutions (more is visible to the camera). A lot more time is spent in the for loop (as expected) in this case. In these situations, I can expect to be in the for loop for as many as ~250 iterations per smoke trail, so ~2500 iterations for 10 smoke trails.
-The code in the "for loop" is the major culprit (my code for mantaining the general smoke trail array, determining which array points are visible each frame, and calculating initial values is fairly fast).
By "frame rate drops significantly," I mean that I can go from a consistent ~400 FPS to ~60 FPS or lower. Now while 60 is not shabby by itself, my game currently does not yet implement any AI, have any other special effects, barely runs any collision detection, and is missing about 98% of the actual "game" that has yet to be built. Basically, the smoke trails are one of the first things I've added, and I can't afford to be spending so much computation time on them when most of the heavy hitting needs to be saved for other, more intensive needs.
So I'm interested in hearing what alternative methods there are for rendering smoke trail effects.