Смотря на этот вопрос с 2010 года, Что касается вершинных буферов в современном OpenGL, все еще ли тот случай, когда прямой доступ к состоянию недоступен с ними? Я изменил большую часть моей графической библиотеки, чтобы использовать DSA с кадровым буфером, текстурой и т. Д., Но мне все еще нужно «связать», чтобы установить состояние моего массива вершин (массив связывания, буфер индекса привязки, буфер привязки вершины, массив отмены привязки и т. Д. ).
Обновление 1: У меня были проблемы с пониманием того, что делают параметры из ответа BDL. Мой модульный тест для очень простого буфера вершин (один атрибут, позиция) дает мне пустой экран (он прекрасно работал со старым методом описания потоков вершин). Предполагается просто нарисовать один треугольник, индексные буферы не требуются.
Вот что я делаю, комментарии — мое понимание:
::glEnableVertexArrayAttrib(vao, // VAO name.
0); // Attribute index (layout in shader).
::glVertexArrayVertexBuffer(vao, // VAO name.
0, // Binding point.
vbo, // VBO name.
12, // Stride (bytes).
0); // Offset (bytes).
::glVertexArrayAttribFormat(vao, // VAO name.
0, // Attribute index (layout in shader).
3, // Component count (x,y,z).
GL_FLOAT, // Type.
GL_FALSE, // Normalised.
0); // Offset (bytes).
::glVertexArrayAttribBinding(vao, // VAO name.
0, // Attribute index (layout in shader).
0); // Binding point.
Теперь, я думаю, я «понял» о связующих точках. Это произвольное число, которое я могу назначить так, чтобы мне было легко и быстро менять другой набор атрибутов. Так что достаточно просто использовать 0 здесь для этого простого теста.
Я использую glCreateBuffers для создания vbo и glCreateVertexArrays для создания vao (изменено по сравнению с предыдущим привязываемым стилем). Отладочной информации нет (контекст отладки включен), каждый вызов проверяется с помощью glGetError, и об ошибках не сообщается.
Обновление 2: шаг и смещение glVertexArrayVertexBuffer были в неправильном порядке. Теперь это работает.
Обновление 3: glVertexArrayVertexBuffer вызывается один раз, а не один раз для каждого атрибута в VBO (если у вас есть чередованная позиция, текстура и т. д.).
Начиная с OpenGL 4.3, большинство состояний VAO можно установить с помощью прямого доступа к состоянию. Посмотрите на следующие функции:
void glVertexArrayAttribBinding (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
void glVertexArrayVertexBuffer (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
void glVertexArrayBindingDivisor (GLuint vaobj, GLuint bindingindex, GLuint divisor);
void glEnableVertexArrayAttrib (GLuint vaobj, GLuint attribindex);
void glDisableVertexArrayAttrib (GLuint vaobj, GLuint attribindex);
void glVertexArrayAttribFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
void glVertexArrayAttribIFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
void glVertexArrayAttribLFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
Вы можете найти некоторые примеры того, как их использовать в этот нить.
В принципе «старый» код VAO можно перевести 1-1 в код DSA. Предположим, у нас есть пример, подобный этому
glBindVertexArray(vao);
glEnableVertexAttribArray(att_idx); //att_idx comes from shader
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(att_idx, 4, GL_FLOAT, GL_FALSE, sizeof(vec4), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
тогда это может выглядеть в коде DSA следующим образом
//glBindVertexArray(vao);
//No translation needed, since we don't want to bind :)
//glEnableVertexAttribArray(att_idx);
glEnableVertexArrayAttrib(vao, att_idx);
Это была легкая часть.
//glBindBuffer(GL_ARRAY_BUFFER, vbo);
//glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(vec4));
Определяет точку привязки <-> Соответствие буфера. Здесь второй параметр является обязательной точкой. Вы можете выбрать здесь в основном то, что вы хотите, пока это < GL_MAX_VERTEX_ATTRIB_BINDINGS. Но я обычно рекомендую использовать тот же индекс, что и у атрибута. Параметры 3 и 4 (Stride, Offset) имеют те же значения, что и в glVertexAttribPointer
, Обратите внимание, что glVertexArrayVertexBuffer
в отличие от glVertexAttribPointer
, не допускайте шаг 0 для указания плотно упакованных данных. Даже когда данные плотно упакованы, шаг должен быть указан в байтах.
glVertexArrayAttribFormat(vao, att_idx, 4, GL_FLOAT, GL_FALSE, 0);
Это определяет формат атрибута. Значения 3-5 похожи на их соответствия в glVertexAttribPointer
, Последний параметр — это относительное смещение между элементами в буфере.
glVertexArrayAttribBinding(vao, att_idx, 0);
Эта строка создает соответствие между индексом атрибута и точкой привязки, используемой в glVertexArrayVertexBuffer
,
Последнее, что не хватает, это индексный буфер:
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glVertexArrayElementBuffer(vao, ibo);
Теперь vao должен быть в том же состоянии, что и со старым кодом.
Других решений пока нет …