Вопрос по c++, opengl, nvidia, opengl-3 – OpenGL 3: glBindVertexArray делает недействительным GL_ELEMENT_ARRAY_BUFFER

6

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

Вот минимальный пример кода 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 с другой стороныnot изменил по звонку. Я проверил спецификацию OpenGL 3.2 (2.10) дляglBindVertexArray и не нашел упоминания об этом неожиданном побочном эффекте.

  1. Is this behavior compliant with the Spec?
  2. If so, what other side effects can be expected from a call to glBindVertexArray?
  3. What is the rationale behind this?

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

Но почему это только изменяет GL_ELEMENT_ARRAY_BUFFER, а не GL_ARRAY_BUFFER? ComicSansMS
@ComicSansMS: К вашему сведению: если вы задаете вопрос об OpenGL, вам следует использовать тег OpenGL. Даже для вопросов OpenGL 3; использованиеboth теги. Nicol Bolas
Я думаю, что связывание VAO неявно связывает буферы массива элементов и вершин. Вот для чего нужны VAO. Если вы связываете VAO, а затем привязываете индекс и буфер вершин, эти буферы затем неявно связываются каждый раз, когда вы связываете VAO позже. Таким образом, связывание VAO выше, по-видимому, неявно устанавливает нулевой элемент и массив вершин в ноль, поскольку они не были включены вами в объект VAO. Это имело смысл? :-) Robinson
Поскольку буфер массива является буфером вершин (по крайней мере, различные glEnableVertexAttribArray и glVertexAttribPointer вызывают ваш make вместе с ним), и он включает в себя элементный буфер как часть этого состояния. Robinson
В этом есть смысл. Однако я все еще немного озадачен тем фактом, что я не смог найти упоминаний об этом побочном эффекте в документах. Мне бы очень хотелось увидеть официальную газету, подтверждающую, что это действительно желаемое поведение. ComicSansMS

Ваш Ответ

1   ответ
14

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

However, I still feel a little puzzled by the fact that I couldn't find any mention of this side-effect in the docs.

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

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

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

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

OpenGL 3.3 specification, section 2.10:

The resulting vertex array object is a new state vector, comprising all the state values listed in tables 6.4 and 6.5.

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

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

Похожие вопросы