Действительно ли «glGenBuffers» важен, если у нас есть glBindBuffer?

#opengl

#c #opengl

Вопрос:

Ну, я начинаю с OpenGL, и, прочитав документацию о glBindBuffer, я немного запутался.

«glBindBuffer привязывает объект buffer к указанной точке привязки буфера. Вызов glBindBuffer, для цели которого установлена одна из принятых символьных констант, а для буфера установлено имя объекта buffer, привязывает имя объекта buffer к цели. Если не существует объекта buffer с именем buffer, создается объект с этим именем. Когда объект buffer привязывается к целевому объекту, предыдущая привязка для этого целевого объекта автоматически нарушается.» Источник: http://docs.gl/gl4/glBindBuffer

Означает ли это, что если я не создаю объект buffer с именем «foo», но вызываю glBindBuffer , он создаст для меня объект с этим именем («foo»)?

Если это так, следующий код должен работать нормально:

 GLuint bar = 70;
glBindBuffer(GL_ARRAY_BUFFER, bar);
  

-> Создайте объект buffer, «соедините» его с помощью bar (70) и привяжите к GL_ARRAY_BUFFER.

Комментарии:

1. Вам нужно думать об именах как о черных ящиках, а не как о целых числах. Предположим, что это действительно сложные непрозрачные значения, поэтому вы хотите, чтобы OpenGL генерировал их для вас при любых обстоятельствах.

Ответ №1:

Нет, этот код будет работать только в контексте профиля совместимости (или OpenGL ES).

Смотрите Спецификацию профиля ядра API OpenGL 4.6 — 2.6.1 Управление объектами — страница 28

[…] команда GenBuffers возвращает одно или несколько ранее неиспользуемых имен объектов буфера.
Сгенерированные имена помечаются символом GL как используемые только для целей генерации имен. Имена объектов, помеченные таким образом, не будут возвращены дополнительными вызовами для генерации имен того же типа, пока имена снова не будут помечены как неиспользуемые путем их удаления […]

Это означает, что glGenBuffers не делает ничего другого, кроме резервирования имен (значений). Дальнейшие вызовы glGenBuffers не будут возвращать те же значения. Если glGenBuffers всегда используется для получения значений имен для объектов буфера, то вы можете быть уверены, что значение еще не используется для другого объекта буфера.

Но в спецификации профиля ядра OpenGL для настольных компьютеров не разрешено использовать имя для glBindBuffer , которое не было зарезервировано (возвращено) glGenBuffers .

Смотрите Спецификацию профиля ядра API OpenGL 4.6 — 6.1 Создание и привязка объектов буфера — страница 62

Ошибка INVALID_OPERATION генерируется, если буфер не равен нулю или имя, возвращенное из предыдущего вызова GenBuffers, или если такое имя с тех пор было удалено с помощью DeleteBuffers.

Эта часть спецификации отсутствует в Спецификации профиля совместимости API OpenGL 4.6 — 6.1 Создание и привязка объектов буфера — страница 62

Это немного сбивает с толку, но такова спецификация.

Это поведение можно проверить с помощью кода вашего вопроса. Следующий код не возвращает ошибку, используя контекст профиля совместимости, но возвращает GL_INVALID_OPERATION с использованием контекста основного профиля:

 GLuint bar = 70;
glBindBuffer(GL_ARRAY_BUFFER, bar); 
GLenum error = glGetError();
  

Комментарии:

1. Итак, чтобы написать код без использования glGenBuffers , вам нужно было бы самому распределять идентификаторы, я полагаю? int lastBuffer = 1; glBindBuffer(GL_ARRAY_BUFFER, lastBuffer ); ?

2. @Rabbid76 Итак, мне нужно СНАЧАЛА создать объект (он же зарезервировать его) с помощью glGenBuffers , а ЗАТЕМ я могу использовать его с glBindBuffer , и если я просто использую «случайное имя», это может сработать, а может и не сработать, в зависимости от того, помечен ли этот объект как «неиспользуемый». Верно? (вкратце: просто выберите безопасный путь: glGenBuffers -> glBindBuffer -> сделайте что-нибудь еще)

3. @Danijel Вы можете зарезервировать кучу имен в начале вашего приложения и управлять ими самостоятельно, когда вам понадобится буфер ta.

Ответ №2:

В спецификации OpenGL 4.6 в разделе 6.1 указано, что glBindBuffer должно генерироваться GL_INVALID_OPERATION исключение, когда buffer не указывает на имя, ранее зарезервированное glGenBuffers :

Ошибка INVALID_OPERATION генерируется, если buffer не равен нулю или имя, возвращенное из предыдущего вызова GenBuffers, или если такое имя с тех пор было удалено с помощью DeleteBuffers.

Та же информация указана в официальных документах.

Я не уверен, почему docs.GL не указывает эту информацию. Возможно, мы неправильно интерпретируем предложение, поскольку в нем указано, что буфер создан. Технически, только имя буфера создается вызовом glGenBuffers , но объект buffer создается, когда имя привязывается в первый раз.

Комментарии:

1. Вы правы, в этом разница по сравнению с OpenGL ES.

2. @Rabbid76: Интересно, не знал, что glBindBuffer ведет себя по-другому в ES. Но это может объяснить, почему docs. GL указывает неверную информацию.