2

I am working on a part of a program where given a collection of xyz-coordinates, a 3D model is made. I have all of the functionality needed for this picture done (i.e. panning, rotating, scaling) however the more xyz-coordinates given, the slower my program runs. My program runs pretty smooth when processing 29,000 coordinates, but I when I have 300,000 points, my program slows down. I am using SharpGL in order to use OpenGL in WPF. The code for inserting all these points looks as follows:

gl.Begin(OpenGL.GL_LINES);

        for (int i = 0; i < (parser.dataSet.Count - 1); i++)
        {

            gl.Color(1.0f, 0.0f, 0.0f);
            gl.Vertex(parser.dataSet[i].X / parser.xDiv, parser.dataSet[i].Y / parser.yDiv, parser.dataSet[i].Z);
            gl.Vertex(parser.dataSet[i + 1].X / parser.xDiv, parser.dataSet[i + 1].Y / parser.yDiv, parser.dataSet[i + 1].Z);
        }

        gl.End();
        gl.Flush();

Am I doing something noobish (im not familiar with OpenGL) that I can fix? Some people have mentioned scaling my data down, which I am not totally opposed to, but is there a way to 'scale back up' as I "zoom"(rescale) in on the picture?

TheBlindSpring
  • 631
  • 5
  • 22

3 Answers3

7

The immediate-mode (glBegin()/glEnd()) function-call overhead for 300,000 points is massive.

Batch up your geometry submission using vertex arrays or vertex buffer objects. That way you can draw all your points in 10-20 calls instead of nearly a million.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • This will give you the most immediate performance boost. I would also recommend exclusively using vertex buffer objects, as they do not have to be sent to the graphics card every frame and are thus facter than vertex arrays. They are a bit more complicated because you're going to have to write shaders to deal with them, but the speedup is worth it. Here's a quick tutorial on them: http://3dgep.com/?p=2596 – redsoxfantom Mar 05 '14 at 21:31
  • @redsoxfantom it's actually possible to use vertex buffers with the fixed function pipeline using either nVidia extensions that provide default values for the attribute locations or using glGetPointerv – Jherico Mar 05 '14 at 21:44
  • I am VERY new to OpenGL and I am using SharpGL so bare with me. @redsoxfantom I looked at this guide, and I am confused as to defining the vertex indeces. I am not really using triangles at all, I am just drawing a line from one point to the next and so on. I don't understand how to find indices. – TheBlindSpring Mar 05 '14 at 21:54
1

To add just a grain of salt, you can optimize divisions out:

divParserDotxDiv=1.0f/parser.xDiv;
divParserDotyDiv=1.0f/parser.yDiv;
gl.Color(1.0f, 0.0f, 0.0f);
for (int i = 0; i < (parser.dataSet.Count - 1); i++)
        {


            gl.Vertex(parser.dataSet[i].X * divParserDotxDiv, 
                      parser.dataSet[i].Y * divParserDotyDiv, 
                      parser.dataSet[i].Z);
            gl.Vertex(parser.dataSet[i + 1].X  * divParserDotxDiv,
                      parser.dataSet[i + 1].Y * divParserDotyDiv, 
                      parser.dataSet[i + 1].Z);
        }

which should be at least %1 to %3 faster :)

huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97
0

genpfault's answer of 'Use vertex buffers' is the correct answer, but it's worth noting that if you're constrained on your target environment and/or can't tackle a port away from the OpenGL 1.x API, there is an alternative in display lists.

With a display list you create and activate a list object (using glGenLists and glNewList) which essentially acts as a recorder for your vertex calls. After you've activated the list you then call your rendering calls (glBegin, glEnd, glVertex, etc) as you normally would. When you're done with the geometry, you call glEndList, which completes the recording. In future when you want to render the same geometry you can simply call glCallList as a shortcut. Because the list data can be captured by the driver and stored on the video card, the overhead is much less.

However, the use of display lists has caveats. There's a whole set of OpenGL functions that can't be called from within a list, and they're only applicable for static geometry. Also, there's no guarantee that the driver will actually store the information on the video card, meaning that there's not necessarily a great performance boost. Your best bet is to migrates away from immediate mode and the fixed function pipeline.

Jherico
  • 28,584
  • 8
  • 61
  • 87
  • You can use VBOs with the fixed-function pipeline just fine. – genpfault Mar 05 '14 at 22:01
  • You're correct. In fact I pointed out the same thing redsoxfan under your answer. What I meant to say was not so much 'port to programmable pipeline' as 'port away from GL 1.x'. Will update my answer. – Jherico Mar 05 '14 at 22:02