Since you would like to use a lot of particles to create more realistic objects, you would like to render them as cheaply as possible. One good candidate primitive is an OpenGL point. Unaliased single points of default size are rendered as single fragments. They can be thought of as very small screen aligned rectangular billboards, since they are always oriented towards the viewer.
It is important to pass points to the graphics hardware as efficiently as possible. Display lists are very efficient, but since the characteristics of the points are usually changing from frame to frame, vertex arrays would be a better choice. Vertex arrays avoid the overhead of multiple function calls per vertex, and have an additional advantage; the primitive data is organized in array form. This is useful since some or all of the point characteristics must be updated by the program each frame. It is important that this be done efficiently, or the updating can become the bottleneck, starving the graphics hardware.
A particle system program has these basic components:
Particles in particle systems can be organized in tables, indexed by the particle, containing particle characteristics to be updated each frame. This representation works well with vertex array representation, since the tables can be used directly to render the updated particles.
|Index||X, Y, Z||R, G, B, A||Vx, Vy, Vz||Lifetime Count|
Interleaved or non-interleaved vertex arrays can be used, depending on the complexity of the particle system parameters. Parameters directly used for rendering, such as x, y, z position can be intermixed in the table with non-rendering parameters, such as current velocity. Vertex array strides can be adjusted to intermix these two types of information, or they can be kept separated. Since particle update performance is important, particle tables may have many non-rendering values to support incremental update algorithms.
When choosing a vertex array representation, keep in mind that OpenGL implementations often have higher performance using interleaved arrays that are densely packed. We recommend using glInterleavedArrays() when possible. Of course, the data structure may have be adjusted to optimize for either rendering speed or particle update performance, depending on which part of the system is the performance bottleneck.