Я запутался с тем, как заполнить мой массив вершин, чтобы он правильно рисовался. Код OpenGL, который я использую:
float vertices[size];
//Here I have a method to populate the array with my values from a 2D matrix
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it
glGenBuffers(1, vboID); // Generate our Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, (size) * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Disable our Vertex Array Object
glBindVertexArray(0); // Disable our Vertex Buffer Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object
glDrawArrays(GL_TRIANGLES, 0, size/3); // Draw
glBindVertexArray(0); // Unbind our Vertex Array Object
Надеюсь, что изображение делает это легче понять. На изображении «А» матрица 3х3 слева показывает, что я получаю, когда рисую треугольники, а матрица справа — это то, чего я пытаюсь достичь.
В настоящее время, когда я создаю массив вершин для рисования, я заполняю его в порядке, показанном на изображении «B». Я добавляю значения в массив, работая со строкой, затем опускаю столбец и повторяю. Так, например:
vertexArray[0] = matrixElement[0].x
vertexArray[1] = matrixElement[0].y
vertexArray[2] = matrixElement[0].z
vertexArray[3] = matrixElement[1].x
vertexArray[4] = matrixElement[1].y
vertexArray[5] = matrixElement[1].z
Этот порядок ввода в vertexArray дает результаты, которые можно увидеть на изображении «C», где создаются неправильные треугольники.
Мой вопрос: каков разумный способ заполнения массива вершин в порядке, который будет создавать треугольники на большой матрице вершин таким образом, который выглядит как правая диаграмма на изображении «A».
Если вы хотите избежать избыточности и нарисовать всю сетку одним вызовом отрисовки, один из вариантов — использовать комбинацию из:
GL_TRIANGLE_STRIP
как примитивный тип.Примитивная функция перезапуска необходима, потому что вы не можете легко представить эту сетку одной треугольной полосой. Используя нумерацию из своего эскиза, вы можете, например, описать топологию с двумя треугольными полосами, используя эти две индексные последовательности:
0 3 1 4 2 5
3 6 4 7 5 8
Настройка и включение примитивного перезапуска могут быть выполнены с этими вызовами:
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
Вы можете выбрать индекс, но общая политика (и единственная опция, поддерживаемая в OpenGL ES) — использовать максимально возможное значение, равное 0xFFFF, если вы используете GLushort
как тип показателей.
Как только примитивный перезапуск включен, «специальный» индекс начнет новую полосу треугольника. Таким образом, две вышеприведенные полосы треугольника теперь могут быть заданы одной последовательностью индекса:
0 3 1 4 2 5 0xFFFF 3 6 4 7 5 8
Вы должны быть в состоянии найти множество примеров, которые показывают, как настроить индексный буфер (вы можете узнать их по их использованию GL_ELEMENT_ARRAY_BUFFER
), поэтому я пропущу эту часть. Тогда розыгрыш:
glDrawElements(GL_TRIANGLE_STRIP, 0, 13, GL_UNSIGNED_SHORT, 0);
где 13 — количество используемых индексов.
Есть альтернативы использованию примитивного перезапуска:
Используйте повторяющиеся вершины. Это была обычная уловка, прежде чем примитивный перезапуск стал широко доступным. Я бы не рекомендовал это больше. Просто для иллюстрации, последовательность индекса в этом случае будет:
0 3 1 4 2 5 5 3 3 6 4 7 5 8
Два повторяющихся индекса приведут к вырожденному треугольнику (0 пикселей), который «соединяет» две полосы треугольника.
glMultiDrawElements()
рисовать несколько треугольных полос с помощью одного вызова рисования.Вы используете GL_TRIANGLES
а также glDrawArrays()
поэтому вам нужно добавить 3 вершины для каждого треугольника:
// first vertex
vertexArray.push_back( matrixElement[0].x );
vertexArray.push_back( matrixElement[0].y );
vertexArray.push_back( matrixElement[0].z );
// second vertex
vertexArray.push_back( matrixElement[3].x );
vertexArray.push_back( matrixElement[3].y );
vertexArray.push_back( matrixElement[3].z );
// third vertex
vertexArray.push_back( matrixElement[1].x );
vertexArray.push_back( matrixElement[1].y );
vertexArray.push_back( matrixElement[1].z );
...
За то, что вы ищете, GL_TRIANGLE_STRIP
будет лучшим выбором, чем GL_TRIANGLES
, Для примера о том, как расположить вершины, см. Вот