Индексы вершин в OpenGL

При рисовании обектов из нескольких полигонов (треугольников) одна и та же вершина может быть задействована несколько раз. Существет способ избежать дублирования информации о вершине. Достаточно сформировать массив из уникальных вершин, а для рисования треугольников использовать индексы нужных вершин из этого массива.
Материалы проекта
OpenGL Elements buffer object []
Описание
Продемонстрирую процесс, происходящий внутри данного проекта. Здача — нарисовать прямоугольник, составленный из двух треугольников.

Если образно описать массив из вершин, то выглядеть он будет так: {A, C, D, A, B, C}. В этом случае каждая литера обозначает весь набор данных о вершине. Как можно видеть из записи массива, информация о вершинах A и C встречается дважды.
Чтобы избежать повторений сформируем массив из уникальных вершин: {A, C, D, B}. Затем сформируем массив из индексов: {0,1,2,0,3,1}. 6 индексов — 6 вершин (2 треугольника). 0 — A, 1 — C, 2 — D, 3 — B. Таким образом может быть воссоздан исходный массив из вершин, но с экономией памяти, так как информация о вершине — это целый набор всевозможных компонент, влючая координаты вершины в трёхмерном пространстве, координаты текстуры и т.п.
В исходном коде формирование описанных массивов выглядит так:
float verts[] = { -0.9, 0.9, 0.0, 0.5, 0.0, 0.9, -0.9, 0.0, 1.0, 1.0, -0.9, -0.9, 0.0, 0.0, 1.0, 0.9, 0.9, 0.0, 0.0, 1.0}; unsigned int inds[] = {0,1,2, 0,3,1}; ... ... ... unsigned int VAO = CreateVAO(verts, sizeof(verts), inds, sizeof(inds));
Функция формирования Vertex Array Object изменена, так как требуется прикрепить информацию об индексах к обекту VAO:
unsigned int CreateEBO(unsigned int* inds, unsigned int size) { unsigned int EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, inds, GL_STATIC_DRAW); return EBO; }; unsigned int CreateVAO(float* verts, unsigned int size, unsigned int* inds, unsigned int sizei) { unsigned int VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); unsigned int VBO, EBO; VBO = CreateVBO(verts, size); if(inds) EBO = CreateEBO(inds, sizei); /* Атрибут 0 соответствует координатам вершины */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); /* Активируем атрибут 0 */ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3*sizeof(float))); glEnableVertexAttribArray(1); /* Активируем атрибут 1 */ return VAO; };
Объект Elements Buffer Object (EBO) точно так же, как и VBO автоматически ассоциируется с активным обектом VAO. Поэтому переменная EBO, как и VBO не задествована в теле функции CreateVAO.
Конструкция if(inds) здесь присутствует на тот случай, если массив из индексов не требуется.
Последнее, что остается поменять в проекте — это процедура рисования треуголников. Теперь вместо метода glDrawArrays нужно использовать метод glDrawElements:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
Здесь GL_TRIANGLES — способ интерпретации набора вершин, 6 — колличество вершин, GL_UNSIGNED_INT — тип данных для хранения каждого индекса, 0 — начальная позиция в массиве из индексов.
Добавить комментарий