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

OpenGL Vertex Indexes example

При рисовании обектов из нескольких полигонов (треугольников) одна и та же вершина может быть задействована несколько раз. Существет способ избежать дублирования информации о вершине. Достаточно сформировать массив из уникальных вершин, а для рисования треугольников использовать индексы нужных вершин из этого массива.

Материалы проекта

OpenGL Elements buffer object []

Описание

Продемонстрирую процесс, происходящий внутри данного проекта. Здача — нарисовать прямоугольник, составленный из двух треугольников.

OpenGL Quad drawing by triangles

Если образно описать массив из вершин, то выглядеть он будет так: {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 — начальная позиция в массиве из индексов.

229

Добавить комментарий

Ваш e-mail не будет опубликован.