PDA

View Full Version : Particle Engine



yoale
06-07-2002, 06:56 PM
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.

SirKnight
06-07-2002, 07:37 PM
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. http://www.opengl.org/discussion_boards/ubb/smile.gif

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?


-SirKnight

yoale
06-07-2002, 08:32 PM
//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 <= distance <= 1
float alpha = 1 - distance;

//Then I just plot the point
glColor4f(1, 0, 0, alpha);
glBegin(GL_POINTS);
glVertex3f(psn[0], psn[1], psn[2]);
glEnd();
}

//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.

yoale
06-07-2002, 08:35 PM
I'll try to post my other method when I have more time. I'll forewarn you, it's not pretty. Thanx again SirKnight!

Adrian
06-08-2002, 12:02 AM
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.
http://www.nvidia.com/dev_content/nvopenglspecs/GL_EXT_point_parameters.txt

This page shows how to implement distance attenuation: http://www.opengl.org/developers/code/features/OGLextensions/OGLextensions.html

yoale
06-08-2002, 02:39 PM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif

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?

Adrian
06-08-2002, 05:16 PM
Move the glBegin(GL_POINTS) & glEnd() outside your FOR loop.

You could also look at using SIMD.
http://cedar.intel.com/cgi-bin/ids.dll/c...ORIAL&catCode=0 (http://cedar.intel.com/cgi-bin/ids.dll/content/content.jsp?cntKey=Generic+Editorial%3a%3agames_pa rticle_systems&cntType=IDS_EDITORIAL&catCode=0)

Jeffry J Brickley
06-08-2002, 05:18 PM
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.

yoale
06-08-2002, 08:31 PM
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)
3. For non-blurred objects, such as sky and terrain, render only if curFrame == 1 (or zero depending on implementation), otherwise render the object(s).
4. 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.
5. 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 http://www.opengl.org/discussion_boards/ubb/smile.gif

V-man
06-09-2002, 08:25 PM
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.

V-man

yoale
06-11-2002, 07:21 PM
Hey V-Man, thanks for the tip on glDrawElements, it works like a charm! Except, I'm using it for something else http://www.opengl.org/discussion_boards/ubb/smile.gif. 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 http://www.opengl.org/discussion_boards/ubb/wink.gif. 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.

ScottManDeath
06-12-2002, 03:41 AM
Hi

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.

Bye
ScottManDeath

Adrian
06-12-2002, 05:07 AM
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).]

zed
06-12-2002, 09:58 AM
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

davepermen
06-12-2002, 11:00 AM
free picture hosting:
http://tyrannen.starcraft3d.net/free

yoale
06-12-2002, 12:10 PM
Thanks for the web-site davepermen http://www.opengl.org/discussion_boards/ubb/wink.gif 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 http://www.opengl.org/discussion_boards/ubb/frown.gif. So just click at the above website and enjoy http://www.opengl.org/discussion_boards/ubb/biggrin.gif http://www.opengl.org/discussion_boards/ubb/biggrin.gif http://www.opengl.org/discussion_boards/ubb/biggrin.gif