Line graph with glDrawArrays and GL_LINE_STRIP from vector

How can I draw a lot of lines with GL_LINE_STRIP, but not draw an extra line between these lines, because it moves to the next value? See Image

enter image description here

Now the red lines represent the actual values ​​for the lines in the chart, but the yellow ones are because they completed the values ​​for line1 and move on to the next, but still draw a line between these values.

The code I use looks like this: vector1 contains all the string values.

glGenVertexArrays(1,&Vector1_VAObject); glGenBuffers(1,&Vector1_VBObject); glBindVertexArray(Vector1_VAObject); glBindBuffer(GL_ARRAY_BUFFER, Vector1_VBObject); glBufferData(GL_ARRAY_BUFFER,vector1.size()*sizeof(GLfloat), &vector1[0] ,GL_STATIC_DRAW); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0); //Clean glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER,0); glBindVertexArray(0); glUseProgram(lineShader->getProgram()); glBindVertexArray(Vector1_VAObject); glDrawArrays(GL_LINE_STRIP,0,vector1.size()); glBindVertexArray(0); 

So my question is: how can I fix this problem? Thus, it moves along the vector and only draws values ​​for the lines, and not when it jumps after completing the drawing of the first line.

+5
source share
2 answers

A draw with GL_LINE_STRIP (or the equivalent of the triangle GL_TRIANGLE_STRIP ) is like putting a pen on paper and drawing something without ever removing the pen. You cannot help but draw a line between two consecutive points.

If you really want to use GL_LINE_STRIP to draw your graph (this is a good idea) and then something else, you will have to create different buffers and draw glDrawArrays many times with different parameters.

So, let vector1 keep the red lines and vector2 yellow. Part of the initialization will look like this:

 // vector1 store glGenVertexArrays(1,&Vector1_VAObject); glGenBuffers(1,&Vector1_VBObject); glBindVertexArray(Vector1_VAObject); glBindBuffer(GL_ARRAY_BUFFER, Vector1_VBObject); glBufferData(GL_ARRAY_BUFFER,vector1.size()*sizeof(GLfloat), &vector1[0] ,GL_STATIC_DRAW); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0); // vector2 store glGenVertexArrays(1,&Vector2_VAObject); glGenBuffers(1,&Vector2_VBObject); glBindVertexArray(Vector2_VAObject); glBindBuffer(GL_ARRAY_BUFFER, Vector2_VBObject); glBufferData(GL_ARRAY_BUFFER,vector2.size()*sizeof(GLfloat), &vector2[0] ,GL_STATIC_DRAW); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE, 3*sizeof(GLfloat),(GLvoid*)0); //Clean glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER,0); glBindVertexArray(0); 

And then part of a draw:

 glUseProgram(lineShader->getProgram()); glBindVertexArray(Vector1_VAObject); glDrawArrays(GL_LINE_STRIP,0,vector1.size()); glBindVertexArray(Vector2_VAObject); glDrawArrays(GL_LINE_STRIP,0,vector2.size()); 
+2
source

You have several options for drawing multiple disabled line strips:

Multiple Drawing Calls

The simplest and most direct approach is that you make multiple calls with a callback. Say you currently have 1000 vertices in your buffer and make a draw call that ends as:

 glDrawArrays(GL_LINE_STRIP, 0, 1000); 

Now, if it’s actually 4 disabled rowset with 250 vertices each, you simply draw each rowset separately:

 glDrawArrays(GL_LINE_STRIP, 0, 250); glDrawArrays(GL_LINE_STRIP, 250, 250); glDrawArrays(GL_LINE_STRIP, 500, 250); glDrawArrays(GL_LINE_STRIP, 750, 250); 

The disadvantage, of course, is that you need multiple calls. So far this is just a moderate number of calls, and each call still creates a significant amount of work, this should be good. For performance reasons, it is undesirable to have many small drawing calls.

glMultiDrawArrays()

There are various calls that allow you to essentially send multiple pivot calls with a single API call. For example, this is equivalent to the above sequence of calls:

 GLint firstA[4] = {0, 250, 500, 750}; GLint countA[4] = {250, 250, 250, 250}; glMultiDrawArrays(GL_LINE_STRIP, firstA, countA, 4); 

As I understand what you are trying to do, this solution may be ideal for you.

GL_LINES instead of GL_LINE_STRIP

If you use GL_LINES for your call calls, each pair of dots will be connected by a separate line, and you can easily have spaces.

However, there is a significant penalty: you need almost twice as many vertices in your buffer, as most vertices will repeat. Where there were n vertices before:

 a0 a1 a2 a3 ... an 

you need 2 * n - 2 vertices for the same geometry:

 a0 a1 a1 a2 a2 a3 a3 ... an 

The advantage is that you can draw everything with a single draw call with as many gaps as you need.

Primitive restart

OpenGL 3.1 and later has a feature called "primitive restart" that can be very handy for cases like the ones you describe. However, this requires the use of an index array. Index arrays are often used anyway if the geometry is more complex, so this is usually not an obstacle. But since you are not using an index array, and there is no real need to use it, you might not want to enter index arrays just to use primitive restart.

I will not include sample code here, but you can find a lot of documentation and examples if you are looking for a “primitive restart of OpenGL”.

+7
source

All Articles