particle engine :quads vs triangles vs point sprites (ogl)

Started by
9 comments, last by Basiror 20 years, 9 months ago
hi i have messed around with point sprites yesterday and to my disappointment i realized that their scaling behaviour doesn t really fit to my particle engine my particles shall not resize with growing/decreasing distance from the viewer so i did some research but no answers whether it is possible to keep the size with point sprites i am for 25000 particles in my engine( you really don t need more then 25000) well 25000 visible + x times as many in the list now i have found some topics about using triangles and applying a texture to them to lower the amount of vertex manipulation so should i use triangles instead of quads or pointsprites or do you have any other suggestions? i am going to use vertex arrays btw sort particles by texture do the vertex manipulations and place them in the right order into the vertex array and then simply draw them thus i get rid of invisible particles and unnecessarry function calls to avoid function call overhead any suggestions? thx in advance
http://www.8ung.at/basiror/theironcross.html
Advertisement
It makes little sense to use GL_QUADS because most 3D cards will make 2 triangles out of it anyway. I always use GL_TRIANGLE_STRIP. I don''t use a vertex array of any sort. Just OGL IM since I create all the vertices on the fly. You could ofcourse adept this method to fill up an array and then render it if you want. Anyway, here''s roughly what I do:

My particle struct just saves one 3D vector for it''s location. The particle engine (emitor) stores stuff like local gravity, texture pointers, particle size, blending functions, etc. Also, I have a camera class which stores the modelview matrix. from this matrix I derive the camera''s up, right and forward vectors (which are matrix[0], matrix[4] and matrix[8]). When it comes to rendering i roughly do this (somewhat pseudocode I think):

void RenderEngine(){  VEC3D up = camera.up * particleSize;  VEC3D right = camera.right * particleSize;  TextureManager.Bind(&particleTexture);  glDepthMask(GL_FALSE);  glBlendFunc(source, dest);  glEnable(GL_BLEND);  for(i=0; i<numParticles; i++)  {    VEC3D v1=particle[i].position - right + up;    VEC3D v2=particle[i].position - right - up;    VEC3D v3=particle[i].position + right + up;    VEC3D v4=particle[i].position + right - up;    glPushMatrix();    glBegin(GL_TRIANGLE_STRIP);      glTexCoord2f(0.0f, 1.0f); v1.VertexToOGL();      glTexCoord2f(0.0f, 0.0f); v2.VertexToOGL();      glTexCoord2f(1.0f, 1.0f); v3.VertexToOGL();      glTexCoord2f(1.0f, 0.0f); v4.VertexToOGL();    glEnd();    glPopMatrix();  }  glDisable(GL_BLEND);  glDepthMask(GL_TRUE);}


Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don''t post crap!

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

well in your case it test this here

the red books says that you should avoid tons of glbegin and glend calls
so in this case gl_quads might improve your performance

the other problem with quads is

i have heard/read that people use triangles to render the particles
thus placing the texture with the correct clamping mode
....

if that works well i would use this as an alternative

glBegin(GL_QUADS);
for(i=0; i{
VEC3D v1=particle.position - right + up;
VEC3D v2=particle.position - right - up; <br>VEC3D v3=particle.position + right + up; <br>VEC3D v4=particle.position + right - up; <br>glPushMatrix(); <br> <br>glTexCoord2f(0.0f, 1.0f); <br>v1.VertexToOGL(); <br>glTexCoord2f(0.0f, 0.0f); <br>v2.VertexToOGL(); <br>glTexCoord2f(1.0f, 1.0f); <br>v3.VertexToOGL(); <br>glTexCoord2f(1.0f, 0.0f); <br>v4.VertexToOGL(); <br><br>glPopMatrix(); <br>}<br>glEnd(); </i>
http://www.8ung.at/basiror/theironcross.html
I could even buffer the whole thing:

void RenderEngine(){  VEC3D up = camera.up * particleSize;  VEC3D right = camera.right * particleSize;  TextureManager.Bind(&particleTexture);  glDepthMask(GL_FALSE);  glBlendFunc(source, dest);  glEnable(GL_BLEND);  float vbuffer[numParticles*12];  float tbuffer[numParticles*8];  for(i=0; i<numParticles; i++)  {    int index=i*12;    int index2=i*8;    VEC3D v1=particle[i].position - right + up;    VEC3D v2=particle[i].position - right - up;    VEC3D v3=particle[i].position + right + up;    VEC3D v4=particle[i].position + right - up;        vbuffer[index+0]=v1.x; vbuffer[index+1]=v1.y; vbuffer[index+2]=v1.z;    vbuffer[index+3]=v2.x; vbuffer[index+4]=v2.y; vbuffer[index+5]=v2.z;    vbuffer[index+6]=v3.x; vbuffer[index+7]=v3.y; vbuffer[index+8]=v3.z;    vbuffer[index+9]=v4.x; vbuffer[index+10]=v4.y; vbuffer[index+11]=v4.z;    tbuffer[index2+0]=1.0f; tbuffer[index+1]=0.0f;    tbuffer[index2+2]=0.0f; tbuffer[index+3]=0.0f;    tbuffer[index2+4]=1.0f; tbuffer[index+5]=1.0f;    tbuffer[index2+6]=0.0f; tbuffer[index+7]=1.0f;  }  glArrayPointer(GL_VERTEX_ARRAY, &vbuffer);  glArrayPointer(GL_TEXTURE_ARRAY, &tbuffer);  glDrawArrays(GL_QUADS, numParticles*4);   glDisable(GL_BLEND);  glDepthMask(GL_TRUE);}


BTW: There's a good article on particle systems on Gamasutra. It comes with source snippets from the Oxygen3D engine. Might be interesting for you.

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don't post crap!

[edited by - sander on July 3, 2003 8:23:08 AM]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

the way you use the arrays slows the entire system down


what you need to do is

create a large array
get the pointer to the first element and then work with pointers


see articles section for improving the speed of your application
http://www.8ung.at/basiror/theironcross.html
Yup, you''re right. And I could speed it up even more by sorting the engines by texture and for each group of engines that use the same texture, use one big buffer, fill it and render those engines all at once. I could also loose all the VEC3D declarations in the loop, or make them static.

Or i could take the advice from your original post (reducing function calls) and do the computations with the up and right vectors on their separate elements in the same line of code as I fill the buffer (provided that I didn''t inline my operator overloads in VEC3D).

I might even try to enable automatic texture coords generation and loose the entire tbuffer but I would have to try that one out. I''m not sure what the effect would be. It''s just a crazy brainwave

But anyway, we''re going off-track. I was trying to help you with your system, not the other way around

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don''t post crap!

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

you could tell me how many particles you can update with your system

without my particle system my engine runs 168 fps faster
i use a 25000 particles linked list which i update every frame

it s a dual list with next and prev points so removing elements of the list is much faster
of course i will never need 25000 particles ingame but thats just a comparsion

right now it runs at 200 fps

without at 368 fps
is that a good result or am i don t something completely wrong

by updating i mean the triangle vertex manipulations to render it
http://www.8ung.at/basiror/theironcross.html
Sorry i''m a bit late but I went to the Graspop Metal Meeting in Belgium (see my thread in the lounge). On about the particles: That''s a tough question to aswer without ripping my code apart but I''ll try Thank god I recently implemented a profiler

Some rework on your data: you need about 2.28 milliseconds to update 25000 particles. That''s about 0.09 ms per 1000 particles.

My profiler: 0.095061 ms for 1170 particles, that''s about 0.08 ms per 1000.

Mine''s a little bit faster than yours and i''m only on a PIII 600 mhz with 128 mb RAM. You probabely have a better system though. Con''s on my test: Some manipulation is done during the renderingpass (exploding the 1 base vertex to 4). I cannot time that properly since the renderingtime depends a lot on how far the particles are away from the viewer (which varies in my game).

Also note: Not all the optimizations of my above posts have been implemented in my current system. It would take too much rework at the moment.

Anyway, I think that 200 fps with 25000 particles is pretty fast

Hope this helps you a bit.

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don''t post crap!

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

200 fps is rendering the scenery skybox and particles


i gonna use vertex buffers once my level format is completely done
http://www.8ung.at/basiror/theironcross.html
Wow, that''s pretty fast. My bare basecode (camera setup, frustum extraction, DXinput and sound update routines, no rendering) alone drops me back to 80 fps but I''m on an old system as I said. It generally proves to be good at least for one thing. All the programs I code, I try to stay above 15 fps on my system. That means that I usually get very high framerates on other systems.

What kind of system are you on?

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don''t post crap!

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

This topic is closed to new replies.

Advertisement