Я заметил странную ошибку в моей программе, которая возникает, когда я связываю VAO несколько раз после вызова glVertexArrayVertexBuffer
. В моем цикле кадров у меня обычно один VAO для одного вызова отрисовки, но иногда я хотел бы использовать один и тот же VAO для нескольких вызовов отрисовки с разными шейдерами. Но это не работает в моей реализации:
while(RUN){
updateBuffers();//updates VAO
drawThis();//binds and unbinds VAO
drawThat();//binds and unbinds VAO -> OpenGL Invalid Operation error at draw call
}
Тогда как это работает:
while(RUN){
updateBuffers();//updates VAO
drawThis();//binds and unbinds VAO
updateBuffers();//updates VAO
drawThat();//binds and unbinds VAO -> works
}
Также это не работает:
updateBuffers();
while(RUN){
drawThis();//OpenGL Invalid Operation error in second frame
}
но это будет работать
updateBuffers();
glBindVertexArray(VAO);
while(RUN){
drawThis();//only makes the draw call
}
glBindVertexArray(0);
… но это не вариант, потому что я также хочу использовать другие VAO в моем цикле кадров (и я хотел бы оставаться гибким с заказом).
Так что эти функции делают внутри?
draw
функции просто связывают VAO и шейдер, делают вызов отрисовки (обычно glDrawElementsInstanced
) а затем отвяжите шейдер и VAO.
updateBuffers
функция обычно пишет в буферный объект (инициализируется с glNamedBufferStorage
через указатель, который отображает весь буфер, используя GL_MAP_WRITE_BIT
, GL_MAP_PERSISTENT_BIT
а также GL_MAP_COHERENT_BIT
флаги. Чтобы гарантировать, что я не перезаписываю какие-либо данные, которые все еще используются GPU, я всегда пишу в другой раздел буфера. Поэтому перед каждым обновлением я увеличиваю смещение записи на размер предыдущего обновления (или устанавливаю его равным 0, если обновление превышает размер хранилища).
И поскольку обновленные данные должны быть видны шейдерам, я должен обновить точки привязки, с которыми также связаны шейдеры. Я делаю это по телефону glBindBufferRange
для однородных буферов (используется единообразными блоками) и glVertexArrayVertexBuffer
для буферов вершин (для атрибутов вершин) при каждом обновлении, чтобы смещения привязки для каждого буфера начинались с позиции обновленных данных.
Это всегда хорошо работает для одинаковых привязок буфера (смещение обновляется с glBindBufferRange
) но когда я обновляю привязку для буфера вершин VAO (с glVertexArrayVertexBuffer
), а затем связать и открепить, что ВАО более одного раза, прежде чем звонить glVertexArrayVertexBuffer
снова я получаю Invalid Operation
ошибка.
Почему glVertexArrayVertexBuffer
заставить ВАО вести себя так? Каков будет правильный подход для обновления смещения привязки VAO к буферу вершин?
Задача ещё не решена.
Других решений пока нет …