Leges Motus Progress – 2D Particle Effects, GL_POINT_SPRITE

A few days ago, I posted a brief description of the beginnings of the new particle effects system in Leges Motus. Since then, I have been working hard to finish up the system to the point where it’s fully usable in-game. It has now reached that state, and is fully integrated with gameplay (though it may be used in more places in the future). Particle effects spawn whenever a player fires, and can be specified for each weapon in a config file.

For this purpose, I have made several improvements and additions to the particle effects system. I have added a “SimpleLineEmitter” class, which can be used to randomly spawn particles along a given line, instead of just at a specific point. This works nicely for tracer trails, and I am currently using it for the rifle’s effect.

Additionally, I have changed the drawing code for particle effects. The original code drew each particle like any other sprite, in immediate mode and with a quad. This was extremely inefficient, so I created a new method in DrawContext that allows drawing an image repeatedly in many places at once using GL_POINT_SPRITE and VertexArrays. This should allow drawing many more particles at a time, because it reduces the number of draw calls significantly.

I keep arrays of the particle centers and colors in the emitter, trying to initialize it to the max number of particles that will be spawned by the emitter at a time, but increasing the size if necessary. These are simply float arrays, with the centers array being twice the size of the number of particles, so it can hold the x, y for each one in sequence, and the colors array being four times the size of the number of particles, so it can hold the RGBA values for each particle in sequence. I bind the sprite I want to draw, and then pass these arrays into the following function (LM_gl and LM_GL are just macros around gl_ and GL_):

void GLESContext::draw_bound_point_sprites(const float vertices[], int n, int size_x, int size_y, const float colors[]) {
LM_gl(Enable, (LM_GL(POINT_SPRITE)));

// Set the size of all the point sprites
LM_gl(PointSize, (max(size_x,size_y)));


// Configure the point array
LM_gl(VertexPointer, (2, LM_GL(FLOAT), 0, vertices));

// Enable the use of the color array
LM_gl(EnableClientState, (LM_GL(COLOR_ARRAY)));

// Configure the color array
LM_gl(ColorPointer, (4, LM_GL(FLOAT), 0, colors));

// use glDrawArrays to draw the points
LM_gl(DrawArrays, (LM_GL(POINTS), 0, n));

// Disable the client states
LM_gl(DisableClientState, (LM_GL(COLOR_ARRAY)));
LM_gl(Disable, (LM_GL(POINT_SPRITE)));

Unfortunately, in standard OpenGL, there does not seem to be an easy way (other than shaders) to specify the size of each image point separately. OpenGLES has glPointSizePointerOES, which would allow specifying a size for each particle alongside the x/y coordinates.

I am very satisfied with the results of this new particle effect system. I think it will add a lot of visual interest to the game. Screenshot:

A bunch of AIs shooting each other, showing off the new particle effects system in Leges Motus.

A bunch of AIs shooting each other, showing off the new particle effects system in Leges Motus.


~ by greywhind on November 27, 2011.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: