first, off VAO только «запоминает» последние привязки атрибутов вершин (и привязку VBO для буфера индекса (GL_ELEMENT_ARRAY_BUFFER_BINDING
), если таковой имеется). Поэтому он не помнит смещения в glDrawElements()
, вам нужно позвонить позже, используя VAO. Это laso не мешает вам использовать чередующиеся массивы вершин. Позвольте мне объяснить:
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 и VBOs для разных частей сетки (так что рисовать отдельные части легко), или вы можете объединить все в одну пару VAO VBO (так что вам нужно не звоните glBind*()
) и используйте несколько звонков glDraw*()
, чтобы нарисовать отдельные части сетки (как видно из кода выше - представьте себе первый glDrawElements()
рисует корабль, а второй рисует башню, вы просто обновляете некоторую матричную форму между вызовами).
Поскольку шейдеры могут содержать несколько матриц модели в униформе, вы также можете кодировать идентификатор ячейки как еще один атрибут вершины и позволить шейдеру вершин выбирать, какую матрицу использовать для преобразования вершины на основе этого атрибута. Эта идея также может быть расширена за счет использования нескольких матриц на одну вершину с некоторыми весами, назначенными для каждой матрицы. Это обычно используется при анимации органических объектов, таких как персонаж игрока (смотрите «скининг»).
Как единые объекты буфера, единственное преимущество заключается в том, что вы можете упаковать в них много данных и что их можно легко разделить между шейдерами (просто привяжите UBO к любому шейдеру, который сможет его использовать). Нет никакого реального преимущества в использовании их для вас, за исключением случаев, когда у вас будут объекты с 1OOOs матриц.
Кроме того, я написал исходные коды из памяти. Дайте мне знать, если есть некоторые ошибки/проблемы ...
Круто я думаю я получаю это с чередованием, должен попробовать. Но я думаю, что вы допустили ошибку, чтобы быть уверенным в том, что в первую очередь glVertexAttribPointer для вершинных позиций, поскольку я понял, что вершинные позиции плотно упакованы в vbo [0], но вы дали ему шаг? Если шаг не равен нулю для позиций, поскольку они не чередуются. – CodeMonkey
Мне нравится идея о ID сетки в шейдере и передать ее как атрибут, но как бы я начал разбирать во многих матрицах в шейдер (как единообразный массив)? Является ли это тем, что я могу использовать UBO для передачи, скажем, 10 различных матриц преобразования для 10 различных башенок и использовать индекс, проанализированный как атрибут, для поиска правильной матрицы внутри шейдера? Это также позволило бы мне использовать функции glMultiDrawElements/Arrays, рисующие целый корабль с несколькими частями за один раз? – CodeMonkey
Привет, хорошее наблюдение с шагом. Но это не ошибка. Либо я мог бы оставить шаг 0, и OpenGL знал бы (со второго и третьего аргументов), что у меня есть поток 3D GL_FLOATS (и, следовательно, размер 3 * sizeof (float)), или я могу рассчитать шаг для него. В этом нет ничего плохого. Для дальнейшего уточнения - шаг - расстояние между адресами двух последовательных вершин, это НЕ пространство между ними (поэтому 0 не означает, что между вершинами нет неиспользуемых байтов, это означает, что OpenGL должен вычислять реальный шаг из числа измерений и используемый тип данных). –