2012-04-03 3 views
7

Я был уверен, что если вы привяжете буфер через glBindBuffer(), вы можете с уверенностью предположить, что он остается связанным, пока цель не отскочит от другого вызова до glBindBuffer(). Поэтому я был очень удивлен, когда я обнаружил, что вызов glBindVertexArray() задает буфер, связанный с мишенью GL_ELEMENT_ARRAY 0.OpenGL 3: glBindVertexArray недействителен GL_ELEMENT_ARRAY_BUFFER

Вот минимальный C++ пример кода:

GLuint buff; 
glGenBuffers(1, &buff); 
std::cout << "Buffer is " << buff << "\n"; 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buff); 
GLuint vao; 
glGenVertexArrays(1, &vao); 

GLint bound_buff; 
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &bound_buff); 
std::cout << "Bound before glBindVertexArray: " << bound_buff << "\n"; 

glBindVertexArray(vao);  
    // ^- an implicit glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); ? 

glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &bound_buff); 
std::cout << "Bound after glBindVertexArray: " << bound_buff << "\n"; 

я запускаю этот код сразу после инициализации OpenGL 3.2 контекст устройства и получить следующий вывод:

Buffer is 1 
Bound before glBindVertexArray: 1 
Bound after glBindVertexArray: 0 

GL_ARRAY_BUFFER с другой стороны, это не изменен вызов. Я проверил версию OpenGL 3.2 (2.10) для glBindVertexArray и не нашел упоминания об этом неожиданном побочном эффекте.

  1. Является ли это поведение совместимым с Spec?
  2. Если да, то каких других побочных эффектов можно ожидать от звонка до glBindVertexArray?
  3. В чем причина этого?

Я тестировал это на карте nvidia на машине Win XPx64 с драйвером WHQL 296.10. Быстрый тест на OS X Lion с nvidia GT330M дал те же результаты.

+0

Я думаю, что привязка VAO неявно связывает буферы элементов и вершин. Для этого нужны VAO. Если вы связываете VAO, а затем связываете буфер индекса и вершины, эти буферы затем неявно привязываются всякий раз, когда вы связываете VAO позже. Таким образом, привязка VAO выше, по-видимому, неявно устанавливает массив элементов и вершин в ноль, поскольку они не были включены вами в объект VAO. Это имело смысл? :-) – Robinson

+0

Но почему это только изменяет GL_ELEMENT_ARRAY_BUFFER, а не GL_ARRAY_BUFFER? – ComicSansMS

+0

Поскольку буфер массива является буфером вершин (по крайней мере, различные glEnableVertexAttribArray и glVertexAttribPointer вызывают ваш make с ним), и он включает в себя буфер элемента как часть этого состояния. – Robinson

ответ

15

Vertex Array Objects инкапсулировать все состояние *, необходимое для визуализации данных вершин. Поэтому они должны инкапсулировать, какие буферы вы связываете с атрибутами (через glVertexAttribPointer), GL_ELEMENT_ARRAY_BUFFER (необходимо для вызовов glDrawElement*) и так далее.

Однако я все еще немного озадачен тем фактом, что я не мог найти упоминания об этом побочном эффекте в документах.

Спецификация четко объясняет это, хотя для этого требуется понимание того, как работает спецификация.

OpenGL - это совокупность состояний, что означает, что все функции OpenGL (за исключением тех, которые фактически что-то отображают) изменяют состояние OpenGL. Когда вы вызываете glVertexAttribPointer, эта функция концептуально модифицирует часть внутреннего состояния OpenGL.

OpenGL objects Определены, какие части состояния OpenGL они инкапсулируют. Таким образом, если функция изменяет состояние, инкапсулированное объектом, то эта функция изменяет сам объект. Связывание объекта означает замену текущих частей состояния, которые они инкапсулируют текущим состоянием этого объекта.

Спецификация определяет VAO на основе того, в каком состоянии они инкапсулируются. Он в основном указывает на одну из таблиц состояний OpenGL и говорит: «VAO - все это». Ядро 3.х версия этой функциональности на самом деле изменяет таблицы состояний, чтобы сделать его немного более четкое (такое же поведение, немного отличается их объяснение):

OpenGL 3.3 спецификации, раздел 2.10:

Полученный объект массива вершин представляет собой новый вектор состояния, содержащий все значения состояния, перечисленные в таблицах 6.4 и 6.5.

Я не собираюсь перепечатывать таблицы 6.4 и 6.5; вы можете посмотреть их сами. Но они, очевидно, включают GL_ELEMENT_ARRAY_BUFFER_BINDING и различные GL_VERTEX_ATTRIB_ARRAY_BUFFER_BIDNING (которые являются буферными объектами).

* Примечание: VAO не содержат состояния, установленные функциями glVertexAttrib. Это может повлиять на рендеринг, если массив атрибутов не включен.

Смежные вопросы