This project is read-only.

Low FPS advice

Aug 16, 2013 at 11:05 PM
Edited Aug 16, 2013 at 11:06 PM
Hi,

I would like to know if someone has any advice on how to do it with better performance.

I'm drawing a 2D dxf file with sharpGL. It has around 300k triangles, so I'm drawing 900k lines. The FPS is very low, about 1-2 FPS. My drawing code is this:
            gl.Begin(OpenGL.GL_LINES);

            gl.Color(cpOriginal.CurrentColor.Color.ScR, cpOriginal.CurrentColor.Color.ScG, cpOriginal.CurrentColor.Color.ScB);

            for (int i = 0; i < Mesh.OriginalFaces.Count; i++)
            {
                var face = Mesh.OriginalFaces[i];

                if ((face.Point1.X >= xmin && face.Point1.X <= xmax &&
                     face.Point1.Y >= ymin && face.Point1.Y <= ymax) ||
                    (face.Point2.X >= xmin && face.Point2.X <= xmax &&
                     face.Point2.Y >= ymin && face.Point2.Y <= ymax) ||
                    (face.Point3.X >= xmin && face.Point3.X <= xmax &&
                     face.Point3.Y >= ymin && face.Point3.Y <= ymax ))
                {
                    gl.Vertex(face.Point1.X, face.Point1.Y);
                    gl.Vertex(face.Point2.X, face.Point2.Y);

                    gl.Vertex(face.Point2.X, face.Point2.Y);
                    gl.Vertex(face.Point3.X, face.Point3.Y);

                    gl.Vertex(face.Point3.X, face.Point3.Y);
                    gl.Vertex(face.Point1.X, face.Point1.Y);
                }
            }

            gl.End();
I check if the triangle has at least one point in the viewport and then I draw 3 lines for each triangle that has a visible point. Performance is improved when I zoom in the drawing because I don't draw what is out of the viewport. But when showing the whole drawing the FPS is really low and slows the the UI controls.
Aug 17, 2013 at 11:18 AM
The first piece of advice is that gl.Vertex is going to be slow, this is immediate mode code (i.e. your client is passing vertex data to the graphics card every frame). What you should try is to use a Vertex Buffer object - that puts the vertex data in the graphics card memory in one hit, then you can tell it the indices to draw, give that a try.
Oct 21, 2013 at 9:57 AM
the second piece of advice is that (assuming you are trying to develop frustum culling) -
  1. simplify your triangle into an AABB(axis aligned bounding box). or simplify even more with bounding sphere. if using sphere, make sure use fast square root(not scientifically accurate but extremely fast and good enough since sphere is already an approximation).
  2. if your scene is stationary, you can subdivide them into hierarchy tree (quadtree or preferably kdtree)
  3. if your scene is dynamic, you could try to learn more about hierarchy tree updates for broad phase collision detection.
people dont normally do frustum culling on a triangle. the cost of rendering a triangle is probably lower than the cost of determining whether the triangle should be rendered. you could try a simple benchmark application by rendering all the triangles using the fastest method available (VBO?) and see how your frustum culling algorithm fares against that.

most probably, the problem domain that you want to tackle is broad phase collision detection.
Jun 23, 2014 at 5:40 AM
Edited Jun 23, 2014 at 5:57 AM
You could also draw triangles instead of lines...
gl.Begin(OpenGL.GL_TRIANGLES);

            gl.Color(cpOriginal.CurrentColor.Color.ScR, cpOriginal.CurrentColor.Color.ScG, cpOriginal.CurrentColor.Color.ScB);

            for (int i = 0; i < Mesh.OriginalFaces.Count; i++)
            {
                var face = Mesh.OriginalFaces[i];

                if ((face.Point1.X >= xmin && face.Point1.X <= xmax &&
                     face.Point1.Y >= ymin && face.Point1.Y <= ymax) ||
                    (face.Point2.X >= xmin && face.Point2.X <= xmax &&
                     face.Point2.Y >= ymin && face.Point2.Y <= ymax) ||
                    (face.Point3.X >= xmin && face.Point3.X <= xmax &&
                     face.Point3.Y >= ymin && face.Point3.Y <= ymax ))
                {
                    gl.Vertex(face.Point1.X, face.Point1.Y);
                    gl.Vertex(face.Point2.X, face.Point2.Y);
                    gl.Vertex(face.Point3.X, face.Point3.Y);
                }
            }

            gl.End();
you will however have to ensure they are in the proper order for visibility...clockwise will disappear and counterclock will show...

there is also a DISPLAY LIST method for drawing the objects once, then only having to recalculate the object if anything changes...this might save you time on subsequent frames...the initial generation frame might be slow, but after it renders once it won't have to recalculate again until another change is made..



check here Redbook Chapter 7 and look near the top of the page...
static void torus(int numc, int numt)
{
   int i, j, k;
   double s, t, x, y, z, twopi;

   twopi = 2 * (double)M_PI;
   for (i = 0; i < numc; i++) {
      glBegin(GL_QUAD_STRIP);
      for (j = 0; j <= numt; j++) {
         for (k = 1; k >= 0; k--) {
            s = (i + k) % numc + 0.5;
            t = j % numt;

            x = (1+.1*cos(s*twopi/numc))*cos(t*twopi/numt);
            y = (1+.1*cos(s*twopi/numc))*sin(t*twopi/numt);
            z = .1 * sin(s * twopi / numc);
            glVertex3f(x, y, z);
         }
      }
      glEnd();
   }
}

static void init(void)
{
   theTorus = glGenLists (1);
   glNewList(theTorus, GL_COMPILE);
   torus(8, 25);
   glEndList();

   glShadeModel(GL_FLAT);
   glClearColor(0.0, 0.0, 0.0, 0.0);
}

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f (1.0, 1.0, 1.0);
   glCallList(theTorus);
   glFlush();
}

Step 1 - Init

create the list and get a uint id
uint ListID = gl.GenLists (1);

Step2 - Init

where you would use glBegin()...glEnd() use glNewList()...glEndList()
gl.NewList(ListID, OpenGL.GL_COMPILE);
[draw your object]
gl.EndList();

Step3 - Draw

Call the list with the saved id where you would normally draw your object
gl.CallList(ListID);
Jun 24, 2014 at 10:28 AM
Building upon the example above, even faster than display lists are vertex buffer arrays, take a look at this code:

https://github.com/dwmkerr/sharpgl/blob/v/2.4/source/SharpGL/Samples/WinForms/ModernOpenGLSample/Scene.cs

In this sample a vertex buffer array is loaded with the data and rendered, the only issue is that you'll have to use a pixel shader to render the scene (this is now the preferred approach in OpenGL anyway). The sample above shows how to do this.