Best approach to draw many line segments?

Hi there, thanks for clicking into a beginner’s post.

I think this question is simple for you guys. But it really stuck me for a while. Here is the scenario,
I want to draw a bunch of line segments in my scene. For sure, I need to draw some “wide” line segments so I use geometry shader to make my line points to triangle strip (lines_adjacency in, triangle_strip out). However, an obvious issue is that these segments connects together because I pass all line segments in a single VBO and drawcall with glDrawArrays(GL_LINE_STRIP_ADJACENCY, …). The reason I want to use ADJACENCY is that I need adjacent vertex to calculate the normal vector of line. I really don’t want to make drawCall for every single line segment. For that reason, I have searched over internet about “instancing”, but it seems not quite fits my scenario, or…am I wrong?

I have thought of using EBO to index the vertices. But I think it works for drawing triangle only because say you could assign indices as “0, 1, 2” and “3, 4, 5” to separate two triangles. But for drawing line strip, I cannot separate two set of line strips because a line only needs two vertices. (I bet you know what I wanna say).

Thanks for any suggestions

Another idea is to pass line-segment id along with the vertices. Then I could use “if/else” check in geometry shader to determine whether emitting vertex. However I remembered when I write some shaders (Cg) in Unity3D. It said it is better not to write any logical expressions in shader because GPU is not good at it.

If you want to draw multiple strips with a single draw call, you can use glMultiDrawArrays() or primitive restarting (glEnable(GL_PRIMITIVE_RESTART) or glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX)).

Thanks! I have made it ticks! Does glMultiDrawArray() only send data from CPU to GPU one time per frame?

How it actually works is a driver implementation detail.

However, if you have your vertex arrays in VBOs, then they’re probably already on the GPU (or sent to the GPU only once assuming you only populate them once). So at least you know the count array has to be sent to the GPU each frame, since you provide a pointer to CPU memory to the draw call, as well as the other parameters (or some driver encoding of them).

You can get around the driver having to send the count array to the GPU each frame by using glMultiDrawArraysIndirect(), which lets you have even that pre-uploaded to the GPU. So all that probably gets sent to the GPU each frame – that you pass in anyway – are the draw call parameters (mode, indirect, drawcount, stride), or some driver encoding of them.

That’s pretty handy, but in some cases you don’t even want the drawcount to come from the CPU – because the GPU is computing it. In that case, you can use glMultiDrawArraysIndirectCountARB() which allows you to feed the drawcount in from a GPU buffer object.