Particle Engine

I have an aesthetic problem with my particle engine. I’m posting it here because I don’t think this is a beginner topic.
First, there are two methods that I’m trying, both with some extreme limitations. In the first method I use a loop inside a glBegin(GL_POINTS) with alpha blending enabled. A mass specifies number of particles, and an equation specifies general form of particles. The thing is, when you get close to the “center of mass”, the particles are so far apart that there is a huge gap between them.
The second method uses glBegin(GL_QUADS) with textures of a particle. After the position and orientation relative to the camera is found, I then use a loop and layer the textures. I rotate the texture randomly in the xy plane and offset each texture from the first with an equation to give the “cloud” its form". The problem with this method is that you can easily see that the same texture is used each time and it EXTREMELY SLOWS DOWN the program when you get close to it.
I hope this all makes sense to someone, and hope someone could help me out. I’d love to be able to render realistic fire.

There are two SIGGRPAH 2002 papers that demonstrate realistic fire. The one by stanford is very impressive to me. I havnt seen the other one yet. But Ii dont think these techniques can be done in real time. I have yet seen a program rendering stuff using the navier-stokes formulas for fluid dynamics in realtime. I hope that will change soon though.

Have you checked out the fire demo done in a shader by nvidia? It looks pretty cool IMHO. They even describe how its done in pretty good detail in Game Programming Gems 2.

Could you maybe tell us what equations your using? Also maybe some pseudo code or something?


//I set up my camera to make sure particles appear in correct place.

int cntPoints; //Number of points to use in rendering
float psn[3]; //Used to determine a point’s position based on a general form equation, such as a sphere or hyperbaloid

for (int pnt = 0; pnt < cntPoints; ++pnt)
//First I randomly find a point’s coordinate using a function
//The coordinate (0,0,0) is so that it is the origin of the object, not the world
//The function returns coordinate values in the range from zero to one

//Then I find the distance of this point from the origin of the particles'
float distance = sqrt(psn[0] * psn[0] + psn[1] * psn[1] + psn[2] * psn[2]);

//The closer to the center, the brighter the point will be
//The further away, the more it blends into the background
//0 &lt;= distance &lt;= 1
float alpha = 1 - distance;
//Then I just plot the point
glColor4f(1, 0, 0, alpha);
	glVertex3f(psn[0], psn[1], psn[2]);


//I know it’s overly simple, but it works fairly well when the viewer is quite aways away and the cntPoints is in the thousands.
//As you can hopefully quickly see, the gaps become quite large when you get near the cloud.//
//I know its because the radius of the cloud and the quantity of particles used is constant.
//And since the cloud should ppear “larger”, when nearing it, the lack of particles makes it look awful.

I’ll try to post my other method when I have more time. I’ll forewarn you, it’s not pretty. Thanx again SirKnight!

If you use distance attenuation with GL_POINTS the particles will become larger as you move closer to them. Distance attenuation can be enabled via the point parameters extension.

This page shows how to implement distance attenuation:

Thank you Adrian for your input. Distance attenuation is a very good idea. There are many particle engines I have heard about that use this method. In fact I had tried it, but in a different way. I used glPointSize(distance), where distance is either distance from viewer, or distance from particle’s source.

When I used distance from viewer, the program slows way down (a big musn’t!)
when I come near the cloud because of having to render large points with blending.

When using the distance from the cloud’s center, the particles in the center of the cloud appear “hotter”, while the outer particles look like sparks. This method seems to run at a constant rate, and looks fairly reasonable for my purposes.

In either case however, to make the cloud look “full”, I need to use at least 10000 points! This bottlenecks my program nomatter what - with or without setting glPointSize, so I don’t think distance attenuation will be of much help to me even if I’m using the extension

Yet, and here’s the quicker Adrian, I WANT to see the particles get bigger when I get close to them. I want a TON of particles. The problem is with rendering time and resources–and I have a GeForce 2 w/64 MB RAM. Sure I get over 100fps now, but I haven’t added character models or terrain yet to the rendering pipeline. Maybe I need an optimiaztion somewhere?

Move the glBegin(GL_POINTS) & glEnd() outside your FOR loop.

You could also look at using SIMD.…ORIAL&catCode=0

I think the distance attenuation should help you. I know I use a combination of items for my particle engine, but I going to see the presentation on fire in hopes of getting some more ideas for improvements. I use 3 textures with random distribution amoung textured tris as well as GL_POINTS with distance attenuation. It’s okay, but I keep trying to make it better every year. After Siggraph 2002, I hope that my particle engine will be better still, I am already coding the shading portion of it but will wait until august before implementing it.

Well, I tried putting the glBegin()/glEnd() statements outside the for loop and noticed a good improvement in performance and visual quality. Thanks for the optimization Adrian!

There is something really cool I stumbled upon that improved my fps from 300-500 or so to around 1200-OR MORE, NO JOKE! And I will tell you helpful people how, no cost!

This idea is similar to motion blur using glAccum(). However, its FAST! It not only improves performance, but adds realism, how cool is that? Here are the main steps to achieve what I believe to be really sweet effects.

  1. For blur to work, you must set a target fps variable, like blur. Set this to the reciprocal of desired fps, say around 1/60. You will have an “actual fps” which is how many frames the program renders to the backbuffer (in my case around 1200). The “observed fps” if possible, is the target fps. If the target fps cannot be reached due to processing overload, the blur can also help to compensate for this.
  2. Keep a variable that determines which frame in blurring the pipeline is currently rendering, like curFrame and intialize it.
  3. Keep a variable that determines total time elapsed since last SwapBuffers, such as refresher. Whenever the rendering algorithm is reached, increment refresher by the difference in time between last call to the rendering algorithm.
  4. Every time the render algorithm is called, ++curFrame. Do not clear the buffers or swap them (yet), continue writing to the same buffer with the previous calls fragments. You could adjust the alpha value of all fragments with a glColor4f() statement, based on curFrame * blur to make the blur apear “faint.” (Assuming blending is enabled)
  5. For non-blurred objects, such as sky and terrain, render only if curFrame == 1 (or zero depending on implementation), otherwise render the object(s).
  6. If refresher is >= blur, then SwapBuffers and ClearBuffers, setting curFrame and refresher back to zero. Make sure to use refresher and not curFrame to swap and clear buffers, as this is synched to real-time, and curFrame is not.
  7. Repeat!

Doing this, I was not only able to have motion blur–a cool effect, but I was able to cheat and add more particles to my cloud because of the processing time saved by not swapping and clearing buffers every pass! Anyone interested in seeing some real code should let me know! The only negative in this is some artifacts because I haven’t figured out how to use glPolygonOffset(). Anyone care to help me in learning glPolygonOffset()?

I hope this tidbit is useful to alot of you

It’s better to issue as less commands as possible to GL. You can easily use glDrawElements with GL_POINTS as the primitive.

Other optimization are possible with vendor specific extensions.

PS: Post a snap shot on the web so that we can see your results.


Hey V-Man, thanks for the tip on glDrawElements, it works like a charm! Except, I’m using it for something else . After some help from this forum, and some of my own thoughts, my particle engine is almost done! My website’s not up and running yet, but I’m more than willing to email you (and anyone else) some jpgs if you’d like . Just reply to this forum and let me know. My engine will also have cool lightning bolt effects too when it is completely finished. Together with the lightning and fire, get ready for PLASMA STORMS! Thanks a million.


if you have a GF3 of GF4 then I think the NV_point_sprites extensions is nice.
It allows to generate texture coords for points, sou you can render texture mapped quads by rendering GL_POINTS.


A few months ago the point sprites extension wasn’t available on the GF3, is it now?

[This message has been edited by Adrian (edited 06-12-2002).]

the main problem is this?

>> The problem with this method is that you can easily see that the same texture is used each time and it EXTREMELY SLOWS DOWN the program when you get close to it.<<

its cause u use a lot of fillrate (with blending i assume) thus u need to combat this (not much u can do)
*try turning on alphatesting as well as blending
*use a polygon that ‘fits’ the prticle shape better, usually quads are better than triangles

free picture hosting:

Thanks for the web-site davepermen I have uploaded a picture called yoales sampling.jpg there. Just so all you know, I ended up using quads afterall for the particles (at least for now). And since I have a GeForce2, I don’t think I can even use point sprites. What a bummer . So just click at the above website and enjoy