Question

I am trying to do some opengl programming using freeglut. Suppose an object(comet/aeroplane) which moves in 3D space and I want render the path traced by it as a point cloud (which represents white trail left behind by aeroplane).

My problem is, I need to clear the screen using glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) every time glutDispFunc is called in-order to give movement to the aeroplane(I am using a keyboardfunction to change the position of the plane). However I also need to display a huge number of points which go on accumulating as the plane moves.I have tried with clear screen using

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

which results in severe performance degradation as the number of points increase but can display the moving plane as well as the cloud of points. Anyone knows how to handle such scenarios?

Was it helpful?

Solution

Yes, you clear screen and redraw everything every time. That's how many game engines work.

However I also need to display a huge number of points which go on accumulating as the plane moves.I have tried with clear screen using

You're probably trying to draw too many particles. 100 particles (or a few hundreds, but less than a thousand) should be enough to draw comets trail. With just 200 (BIG) particles, you can create very convincing cloud.

Also, you don't need points to draw comet trail. Using alpha-blending you can draw semi-transparent light-saber-like lines easily using triangles.

Light-saber-like, plasma-like, flame-like should use any color with small tint of white (rgb 255, 10, 10, for example), and are traditionally drawn using glBlendFunc(GL_SRC_ALPHA, GL_ONE)

Here are few examples. Examples show triangular mesh you should use. Numbers indicate alpha. 0 - fully transparent, 1 - fully opaque. slashes indicate triangulation, when necessary. "|" and "-" indicate face edges:

glowing line

 0--0--0--0
 | \|  | /|
 0--1--1--0
 | /|  | \|
 0--0--0--0

 repeat
 0--0
 |  |
 1--1
 |  |
 0--0
 to add more segments

thick glowing line

 0--0--0--0
 | \|  | /|
 0--1--1--0
 |  |  |  |
 0--1--1--0
 | /|  | \|
 0--0--0--0
repeat
 0--0
 |  |
 1--1
 |  |
 1--1
 |  |
 0--0
to add more segments.

You can use something like that for comet trail. And add few small particles for sparks or something. Also don't forget about textures. Using textures you can easily add more details than if you were trying to draw everything using untextured geometry.

--edit--

aeroplane's white trail

To implement smoke of any kind...

  1. you need to use very BIG textured particles with "smoky"/"cloudy" texture. If you google "smoke particle texture" on google images, you'll see what I'm talking about.
  2. Those "big" particles cannot be normally drawn using point sprites (because it can be bigger than screen at close distance) and require "billboards". Billboard is a square that always faces camera.
  3. Ideally color channel of smoke texture should be completely white (so you can color individual particles using vertex color), and "smoke" should be painted on alpha.
  4. Smoke particles should be sorted by depth when you draw them and should be rendered from farthest to nearest (from camera). Insertion sort algorithm works well with "partially sorted" data.
  5. Smoke particles should be rendered with depth write disabled (glDepthMask(0), if I remember correctly)
  6. Smoke particles should use glBlendFunc(GL_SRC_ALPHA, GL_INV_SRC_ALPHA) blending.
  7. However, if there's flame within smoke, flame should use glBlendFunc(GL_SRC_ALPHA, GL_ONE). Flame particles should be either intermixed with (i.e. sorted by depth along with them), or drawn after the smoke (if it uses separate particle system).
  8. To make smoke realistic, assign small initial velocity to all particles, slowly increase their size with time, and make them become more transparent. When particles become completely transparent, remove them from particle system.
  9. When drawing semi-transparent alpha blended surface, enable alpha-test and cut off pixels with alpha==0. This will speed up rendering. (Important, because you can kill framerate with too many smoke particles even on decent hardware)
  10. using many billboard smoke particles can be expensive especially if they're very close, so if you want to fill large area with this smoke and particles are going to be large and float at eye level, covering entire screen area with semi-transparent surfaces multiple times, you might want to research some other volumetric fog technology.
  11. Do not move individual particles using matrices. Do not draw one particle per call. Draw them all in one go, this will be much faster.

OTHER TIPS

If you're not using them already, you should draw with glDrawArrays, which takes an array of points, for example, and draws everything with just one function call. It's much faster than the immediate drawing API (glBegin and glEnd). You may set it up like this:

float points[100][3];
int pointsCount = 0;
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), points);

Then, each time the object "produces" a dot (say, every frame), you may add its position to the array:

points[pointsCount][0] = object.x;
points[pointsCount][1] = object.y;
points[pointsCount][2] = object.z;
pointsCount++;

And then, draw them like this:

glDrawArrays(GL_POINTS, 0, pointsCount);

Of course, you must do something when the array fills up, but you get the idea.

There's also VBOs, which can increase speed even more, but are a more advanced feature.

EDIT: Yes, you should redraw everything with this method. I'd say it won't still hamper performance for quite a bit more points than glBegin/End. According to answers here, you should be able to resize the buffer with glBufferData, but may have to store the current data on your array and transfer it back once you resize it.

Yes, most games work by erasing the screen and redrawing it every frame. However, it might be possible to do MUCH less work per frame, too. Is there anything else on the screen besides the trail? How long should this trail be? Does it have to stay constant-length across time (as opposed to fading out over time much like a mouse trail)?

If you can afford to fade-away your trail, you can use buffer feedback. This technique renders a semi transparent quad over the screen (or object + trail) in question which has the effect of fading away the furthest part of the tail to the background color. The object is then drawn at the new position, creating the brightest part of the tail again. This is a fairly common demo/visualization effect and can create really great looking tails with very little per-frame drawing overheads.

This is perhaps not exactly what you need (I wrote this before you clarified your need as a comment to @SigTerm's answer), but I'm going to leave it here because someone else might need this sort of "trail".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top