6
\$\begingroup\$

I have been looking into using some software to perform industrial-scale DEM simulations. These type of simulations will require millions of particles to be simulated.

Currently, the software I would like to use has some notable performance issues when visualizing the results during the simulation when using openGL. It turns out the part of the code responsible for drawing the particles is this:

void Draw_ParticleGeometry_Sphere()
{
  SetColor_Ramp();

//if(m_OpenGL.Debug_Lines==1)
//{
//  Gl_WireframeP = true;
//}

  for( int i=0; i<m_num_KParticleObjects; i++ )
  {
     glNewList(10+i,GL_COMPILE);

    if(m_OpenGL.color_type==0)
    {
     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Col[i]);
     glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular);
     glMaterialfv(GL_FRONT, GL_EMISSION, materialEmission);
     glMaterialf(GL_FRONT, GL_SHININESS, shininess);
    }
          glPushMatrix();

          glutSolidSphere(m_KParticleObject[i].radius,20,20);

          if(Gl_WireframeP)
          {

                 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Col[6]);
                 glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular);
                 glMaterialfv(GL_FRONT, GL_EMISSION, materialEmission);
                 glMaterialf(GL_FRONT, GL_SHININESS, shininess);
            glutWireSphere(m_KParticleObject[i].radius*1.02f,15,15);
          }
          glPopMatrix();

     glEndList();

  }

}

To be fair I'm new to openGL, but it seems to me that this piece of code loops over all particles, assigns them attributes and add them to a list. Generally, looping like this is not very efficient for a large number of elements. I have been reading up in visualizing particles in openGL and it seems instancing would be a better fit. My questions are:

  • Is looping over all particles like this an efficient way of handling such large systems of particles in openGL?
  • Is there an alternative to looping over all particles?
  • How could this code be improved?
\$\endgroup\$
  • \$\begingroup\$ Is there any alternative to looping over all particles? \$\endgroup\$ – Simon Forsberg Aug 26 '16 at 6:46
  • \$\begingroup\$ @SimonForsberg that's what I would like to find out. I dont know. \$\endgroup\$ – nluigi Aug 26 '16 at 7:22
  • \$\begingroup\$ Is it absolutely necessary to draw each particle as a sphere? The usual approach would be to use textured quads (aka billboards) which would only take up to 4 verts per particle. Also, use modern OpenGL (v3+) and pack your data in a vertex buffer. It will accelerate things significantly. You can also consider instanced rendering and transformer feedback once you port the code the GL3+. \$\endgroup\$ – glampert Aug 26 '16 at 8:35
  • \$\begingroup\$ @glampert no it's not necessary to draw as spheres. This sounds good, would you be willing to format your comment into an answer? Perhaps with some code snippets to clarify? \$\endgroup\$ – nluigi Aug 26 '16 at 9:16
2
\$\begingroup\$

Basic optimizations

There are a number of possible optimizations you could apply to your problem. Particle simulation real-time rendering is a well researched topic and I think you will be able to find a lot of material on the subject. In particular, look into game development-related research. Games make heavy use of real-time particles. The GPU Pro series might be a good place to start.

The first basic optimization to unlock would be to port your code to modern, shader-based OpenGL (starting from GL version 3 and above). Note that I use the term port. It will be a major change from the legacy OpenGL used in your example, but it is the only way you can take full advantage of the current graphics hardware on the market.

Start by changing your rendering code to use Vertex Buffers. This by itself will make things more efficient by reducing CPU/GPU traffic and the number of API calls. A full explanation on Vertex Buffers would be beyond the scope of this answer, plus it is a common introductory subject on modern OpenGL, so you can find dozens of tutorials out there.

Once you have your Vertex Buffers and shaders set up, you might consider reviewing the way you are drawing the particles. Rendering a full sphere for each particle is very inefficient. They are far too small to require a large number of vertices, in general. All real-time applications and games "fake" particles by drawing a textured quadrilateral per particle that always faces the viewer/camera. When you add alpha blending to the texture, results look quite convincing, even with the simplest of approaches. You can find some samples at my website.

After you have made these major conversions, remember to look into view-dependent culling. It is likely that for any given view of your scene, some or even most particles will not be visible. It is usually more efficient to spend some time testing for the potentially visible geometry and them culling the non-visible parts than to just submit everything to the GPU at every frame. The simplest form of viewport culling is the frustum culling.

Going further

Once you have looked into the above, it might still not be enough for the throughput you need. It will then be the time to start looking into Instanced Rendering and Transform Feedback. Using Compute Shaders might also help accelerating things if you can perform some of the simulation in the GPU as well as the rendering.

I hope these pointers can give you some perspective and a rough roadmap to follow. To know more about each of the topics, I suggest searching the StackOverflow and GameDev.SE sites, as well as good ol Google.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.