Буфер, в настоящее время связанный с GL_ELEMENT_ARRAY_BUFFER
target в OpenGL является частью состояния, содержащегося в объекте Vertex Array (далее VAO). В соответствии со спецификацией профиля ядра OpenGL 4.4 может показаться, что попытка изменить или получить доступ к GL_ELEMENT_ARRAY_BUFFER
в то время как никакой VAO не связан, ошибка:
10.4. Объекты Vertex Array
…
INVALID_OPERATION
ошибка генерируется любыми командами, которые
изменять, рисовать или запрашивать состояние массива вершин, когда нет массива вершин
связан. Это происходит в начальном состоянии GL и может происходить как
Результат BindVertexArray или побочный эффект DeleteVertexArrays.
Это поддерживается вики OpenGL Буферный объект страница:
GL_ELEMENT_ARRAY_BUFFER
Все функции рендеринга формы
gl*Draw*Elements*
будет использовать указатель
поле в виде байтового смещения от начала объекта буфера, привязанного к этому
цель. Индексы, используемые для индексированного рендеринга, будут взяты из буфера
объект. Обратите внимание, что эта цель привязки является частью состояния объектов Vertex Array,
так что ВАО должен быть связанным перед связыванием буфера здесь.
Теперь было бы хорошо, если бы это было не так. Это позволит легко создавать и управлять индексными буферами отдельно от любого конкретного VAO. Но если просто привязать буфер к GL_ELEMENT_ARRAY_BUFFER
verboten, когда нет привязки к VAO, единственная альтернатива для класса, представляющего буфер индекса, для привязки фиктивного VAO при их создании / обновлении / и т.д.
Николь Болас отлично OpenGL учебник говорит, что этот тип использования действительно действителен:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER)
: Вызов этого без привязки к VAO не подведет.
Кажется, это противоречит стандартным вики и opengl.org. Есть ли что-то в стандарте, поддерживающем это, что я пропустил, или это относится только к контекстам профиля совместимости, где использование VAO не требуется?
Если у вас есть AMD или NV GPU, вы всегда можете использовать EXT_direct_state_access
расширение для манипулирования буферным объектом без его привязки (это чисто драйверная функция и не требует какого-либо специального класса оборудования). К сожалению, Intel, Mesa и Apple не удосужились реализовать это расширение, несмотря на его 5-летнее существование — ленивые бездельники.
Посмотрите на следующие функции, они значительно облегчат то, что вы описываете:
glNamedBufferDataEXT (...)
glNamedBufferSubDataEXT (...)
glMapNamedBufferEXT (...)
glUnmapNamedBufferEXT (...)
Теперь, поскольку адаптация DSA редка, вам, вероятно, придется написать запасной код для систем, которые его не поддерживают. Вы можете воспроизвести функциональные возможности DSA, написав функции с идентичными сигнатурами функций, которые используют фиктивные VAO для привязки VBO и IBO для манипулирования данными в системах, которые не поддерживают расширение. Вы должны будете отследить, что было связано с VAO, прежде чем использовать его, и восстановить его до того, как упомянутая функция вернется, чтобы устранить побочные эффекты.
В хорошем движке вы должны скрывать состояние привязки VAO, а не запрашивать его у GL. То есть вместо использования glBindVertexArray (...)
непосредственно вы реализуете систему, которая упаковывает этот вызов и поэтому всегда знает, что VAO связано с конкретным контекстом. В конце концов, это делает эмуляцию функциональности DSA там, где не поддерживается драйвер много более эффективным. Если вы пытаетесь что-то подобное, вы должны знать, что glDelete (...)
функции неявно отменяют привязку (путем связывания 0) удаляемый объект, если он связан в текущем контексте.
Других решений пока нет …