PDA

View Full Version : Proper way to draw lines efficiently



impala454
02-12-2015, 02:33 PM
Hello, I'm a long time C++ developer who's dabbled (and I mean lightly dabbled) in OpenGL from time to time. I'd like to build a real time plotting application using OpenGL as the method of drawing (mainly to keep it fast and cross platform). I've installed GLFW (would link but I'm not allowed to yet) and have a super simple example running so far. The render loop just looks like this:

while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_LINE_STRIP);
glVertex2f(0, 0);
glVertex2f(1, 1);
glEnd();

glfwSwapBuffers(window);
glfwPollEvents();
}
Obviously all this does is draw a diagonal line with two points. What I'd like to know is a few design considerations and how they fit in. The data I'll be plotting will be fairly large arrays or maps of points, usually some value vs time (just say, in milliseconds for now). My initial thought is something like this:

Load all the initial points
Draw them all
Get more data points
Shift the previous drawing to the left by X number of points
Add the new points to the drawing
Delete old points which go off the screen (creating a paging effect)

Is that a valid method to do what I'm describing? I'd like it to be very high performance, as some data could be coming in at 500 kHz or faster. Any suggestions/help would be greatly appreciated.

Cornix
02-12-2015, 02:37 PM
If you want good performance then immediate mode (the glBegin ... glEnd stuff) is probably not what you want to do. It is old and deprecated, mainly because it is slow.
If you want to improve performance you should try to minimalize the number of openGL calls that happen in each frame. You could do this by uploading your vertex data to a vertex buffer object and rendering that instead. But if your data changes in every frame there might be even better solutions. (I just know the basics of OpenGL myself)

GClements
02-12-2015, 04:33 PM
As Cornix says, avoid glBegin/glEnd, use glDrawArrays() with a vertex buffer. Using a vertex buffer means that you only need to transfer data from system memory to video memory once, as it comes in, rather than each frame (as would be the case with client-side arrays).

You probably want to use a circular buffer, to avoid having to shift old data within the buffer. This can be drawn with 2 glDrawArrays() calls (or one glMultiDrawArrays() call): one for the range from the logical start (somewhere in the middle of the physical buffer) to the physical end, the other for the range from from the physical start to the logical end. One minor tweak is required: the first and last physical elements must be the same so that you don't lose the line segment where the buffer wraps around.

If the data are evenly-spaced in time, the X coordinates can remain constant; you just need to apply the appropriate transformation before each draw call. If you use shaders, the X coordinates can be omitted from the buffer and calculated in the vertex shader, meaning that you can copy the raw sample data directly to the vertex buffer.

impala454
02-12-2015, 07:52 PM
Thanks for the replies. The data won't necessarily be evenly spaced, so I may have to do some fiddling with it. Is there a good sample of using glDrawArrays handy? I'm sure the Google has some but I keep turning up old code w/the glBegin/End stuff. I figure since it's essentially just a never ending line it shouldn't be terribly difficult. I think the interaction will be the difficult part (clicking/zooming/auto scaling/etc).