рисование чередующегося VBO с помощью glDrawArrays

#opengl #vbo

#opengl #vbo

Вопрос:

В настоящее время я использую glDrawElements для рендеринга с использованием нескольких VBO (вершина, цвет, текстура и индекс). Я обнаружил, что очень немногие вершины являются общими, поэтому я хотел бы переключиться на glDrawArrays и один чередующийся VBO.

Я не смог найти наглядный пример того, как 1) создать чередующийся VBO и добавить к нему quad или tri (vert, color, texture) и 2) делать все необходимое для его рисования с помощью glDrawArrays. Каков код для этих двух шагов?

Ответ №1:

У меня в голове не укладывается:

 //init
glBindBuffer(GL_ARRAY_BUFFER, new_array);
GLfloat data[] = { 
    0.f, 0.f, 0.f, 0.f, 0.f,
    0.f, 0.f, 100.f, 0.f, 1.f,
    0.f, 100.f, 100.f, 1.f, 1.f,
    0.f, 100.f, 100.f, 1.f, 1.f,
    0.f, 100.f, 0.f, 1.f, 0.f,
    0.f, 0.f, 0.f, 0.f, 0.f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

// draw
glBindBuffer(GL_ARRAY_BUFFER, new_array);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 5*sizeof(GLfloat), NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 5*sizeof(GLfloat), ((char*)NULL) 3*sizeof(GLfloat) );
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  

В этом коде нет ничего особенно волшебного. Просто посмотрите, как:

  • Загружаются данные из data массива: как есть, все смежные
  • шаг для различных атрибутов установлен равным 5 * sizeof (GLfloat), поскольку это то, что есть в данных: 3 поплавка для позиции и 2 для texcoord. Примечание стороны, обычно требуется, чтобы это было степенью 2, в отличие от здесь.
  • смещение вычисляется от начала массива. итак, поскольку мы сохраняем вершину первой, смещение для вершины равно 0. texcoord сохраняется после 3 плавающих данных о местоположении, поэтому его смещение равно 3 * sizeof (GLfloat).

Я не включил туда цвета по определенной причине: обычно они хранятся как ненормированные, что приводит к более запутанному коду инициализации. Вам необходимо сохранить как GLfloat, так и GLubyte в одном блоке памяти. На этом этапе структуры могут помочь, если вы хотите сделать это в коде, но это во многом зависит от того, откуда в конечном итоге поступают ваши данные.

Комментарии:

1. Я надеюсь, что это нормально комментировать так поздно после того, как был сделан пост — но какова причина для того, чтобы сказать «Примечание стороны, вы обычно хотите, чтобы это было степенью 2, в отличие от здесь.»? Если вы используете только координаты positions и tex, где бы вы заполнили дополнительные данные, чтобы получить степень двойки? Кроме того, вы имеете в виду, что размер массива данных должен быть степенью двойки или шагом при вызове функции?

2. Это действительно исходит из прошлого опыта людей, которые пробовали его и обнаружили, что он работает лучше с коэффициентами двойки. Вы не должны следовать этому совету и выполнять его вслепую, а скорее убедиться, что он улучшается. Суть в том, что любая форма кэша между памятью и шейдером, скорее всего, будет работать в режиме power of two. Да, я бы посоветовал дополнить данные, если требуется. Кроме того, если ваш набор данных содержит какой-либо серьезный контент, у вас обычно есть много атрибутов с гибкостью в отношении того, какой тип данных использовать. Разработчики делают мудрый выбор, чтобы «вписаться» в двойную степень