сначала, выключено VAO только «запоминает» последние привязки атрибутов вершин (и привязку VBO для буфера индекса (GL_ELEMENT_ARRAY_BUFFER_BINDING
), если он есть). Таким образом, он не запоминает смещения в glDrawElements()
, вам необходимо вызвать его позже при использовании VAO. Это не мешает вам использовать чередующиеся массивы вершин. Позвольте мне попытаться объяснить:
int vbo[3];
glGenBuffers(3, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, data0, size0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, data1, size1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data2, size2);
// create some buffers and fill them with data
int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// create a VAO
{
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); // not saved in VAO
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), NULL); // this is VAO saved state
glEnableVertexAttribArray(0); // this is VAO saved state
// sets up one vertex attrib array from vbo[0] (say positions)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); // not saved in VAO
glVertexAttribPointer(1, 3, GL_FLOAT, false, 5 * sizeof(float), NULL); // this is VAO saved state
glVertexAttribPointer(2, 2, GL_FLOAT, false, 5 * sizeof(float), (const void*)(2 * sizeof(float))); // this is VAO saved state
glEnableVertexAttribArray(1); // this is VAO saved state
glEnableVertexAttribArray(2); // this is VAO saved state
// sets up two more VAAs from vbo[1] (say normals interleaved with texcoords)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]); // this is VAO saved state
// uses the third buffer as the source for indices
}
// set up state that VAO "remembers"
glBindVertexArray(0); // bind different vaos, etc ...
Позже ...
glBindVertexArray(vao); // bind our VAO (so we have VAAs 0, 1 and 2 as well as index buffer)
glDrawElements(GL_TRIANGLE_STRIP, 57, GL_UNSIGNED_INT, NULL);
glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_INT, (const void*)(57 * sizeof(unsigned int)));
// draws two parts of the mesh as triangle strips
Итак, вы видите ... вы можете рисовать чередующиеся массивы вершин, используя glDrawElements
, используя один VAO и одно или несколько VBO.
Чтобы ответить на вторую часть вашего вопроса, у вас могут быть разные VAO и VBO для разных частей сетки (так что рисовать отдельные части легко), или вы можете объединить все в одну пару VAO VBO (так что вам не нужно часто вызывайте glBind*()
и используйте несколько вызовов glDraw*()
для рисования отдельных частей сетки (как видно из кода выше - представьте, что первый glDrawElements()
рисует корабль, а второй - башню, вы просто обновляете некоторую матричную униформу между звонками).
Поскольку шейдеры могут содержать несколько матриц вида модели в униформе, вы также можете закодировать идентификатор сетки в качестве другого атрибута вершины и позволить вершинному шейдеру выбирать, какую матрицу использовать для преобразования вершины, на основе этого атрибута. Эта идея также может быть распространена на использование нескольких матриц на одну вершину с некоторыми весами, назначенными для каждой матрицы. Это обычно используется при анимации органических объектов, таких как персонаж игрока (ищите «скиннинг»).
По мере того как объекты унифицированного буфера работают, единственное преимущество состоит в том, что вы можете упаковать в них много данных и легко распределить их между шейдерами (просто привяжите UBO к любому шейдеру, который может его использовать). Нет реального преимущества в использовании их для вас, за исключением случаев, когда у вас есть объекты с 1OOO матриц.
Кроме того, я написал выше исходные коды из памяти. Дайте мне знать, если есть ошибки / проблемы ...