Линейный график с glDrawArrays и GL_LINE_STRIP из вектора

Как я могу нарисовать много линий с помощью GL_LINE_STRIP, но не рисовать дополнительную линию между этими линиями, потому что она переходит к следующему значению? Посмотреть изображение

введите описание изображения здесь

Теперь красные линии — это фактические значения для линий на графике, а желтые — потому что он завершил значения для line1 и переходит к следующему, но все же рисует линию между этими значениями.

Код, который я использую, выглядит следующим образом: vector1 содержит все значения строк.

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);

Итак, мой вопрос, как я могу решить эту проблему? Таким образом, он проходит по вектору и рисует только значения для линий, а не тогда, когда его значение переходит после завершения рисования первой линии.

5

Решение

Ничья с GL_LINE_STRIP (или эквивалент треугольника GL_TRIANGLE_STRIP) это как положить ручку на бумагу и нарисовать что-то без Когда-либо снять ручку Вы не можете не провести границу между двумя последовательными точками.

Если вы действительно хотите использовать GL_LINE_STRIP чтобы нарисовать свой график (что является хорошей идеей), а затем что-то еще, вам придется создавать разные буферы и рисовать много раз glDrawArrays, с разными параметрами.

Итак, давайте предположим, vector1 хранить красные линии и vector2 желтый. Часть инициализации будет выглядеть так:

// 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);

А затем часть розыгрыша:

glUseProgram(lineShader->getProgram());

glBindVertexArray(Vector1_VAObject);
glDrawArrays(GL_LINE_STRIP,0,vector1.size());

glBindVertexArray(Vector2_VAObject);
glDrawArrays(GL_LINE_STRIP,0,vector2.size());
2

Другие решения

У вас есть несколько вариантов рисования нескольких отключенных полосок:

Многократные розыгрыши

Самый простой и прямой подход состоит в том, что вы делаете несколько вызовов отрисовки. Допустим, у вас есть 1000 вершин в буфере, и вы выполняете вызов отрисовки, который заканчивается следующим образом:

glDrawArrays(GL_LINE_STRIP, 0, 1000);

Теперь, если это на самом деле 4 несвязанных набора линий по 250 вершин в каждой, вы просто рисуете каждый набор линий отдельно:

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

Недостатком является, конечно, то, что вам нужно несколько вызовов отрисовки. Пока это только умеренное количество вызовов, и каждый вызов все еще генерирует значительный объем работы, это должно быть хорошо. По соображениям производительности нежелательно иметь много небольших вызовов отрисовки.

glMultiDrawArrays()

Существуют различные вызовы, которые позволяют по существу отправлять несколько вызовов отрисовки одним вызовом API. Например, это эквивалентно последовательности вызовов выше:

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

Как я понимаю, что вы пытаетесь сделать, это решение может быть идеальным для вас.

GL_LINES вместо GL_LINE_STRIP

Если вы используете GL_LINES для ваших розыгрышей каждая пара точек будет соединена отдельной линией, и вы можете легко иметь пробелы.

Однако есть существенное наказание: вам нужно почти в два раза больше вершин в буфере, так как большинство вершин будет повторяться. Где ты раньше был n вершины:

a0 a1 a2 a3 ... an

тебе нужно 2 * n - 2 вершины для той же геометрии:

a0 a1 a1 a2 a2 a3 a3 ... an

Преимущество заключается в том, что вы можете рисовать все с помощью одного колла, с таким количеством пробелов, сколько вам нужно.

Примитивный рестарт

В OpenGL 3.1 и более поздних версиях есть функция, называемая «примитивный перезапуск», которая может быть очень удобной для случаев, подобных описанному вами. Однако для этого необходимо использовать индексный массив. Индексные массивы часто используются в любом случае, если геометрия более сложная, так что это обычно не является препятствием. Но так как вы не используете индексный массив, и в вашем случае использования нет реальной необходимости, вероятно, не стоит вводить индексные массивы только для использования примитивного перезапуска.

Я не собираюсь включать здесь пример кода, но вы сможете найти множество документации и примеров, если вы ищете «перезапуск примитива OpenGL».

7

По вопросам рекламы [email protected]