Явное vs Автоматическое привязка местоположения атрибутов для шейдеров OpenGL

При настройке расположения атрибутов для шейдерной программы OpenGL вы сталкиваетесь с двумя вариантами:

glBindAttribLocation(), прежде чем ссылаться на явное определение местоположения атрибута.

или

glGetAttribLocation() после ссылки, чтобы получить автоматически назначенное местоположение атрибута.

Что такое утилита для использования одного над другим?

И какой из них, если таковой имеется, предпочтительнее на практике?

Ответ 1

Я знаю одну серьезную причину, чтобы предпочесть определение явного определения местоположения.

Учтите, что данные геометрии хранятся в Объекты вершинного массива. Для данного объекта вы создаете VAO таким образом, чтобы индексы соответствовали, например:

  • индекс 0: позиции,
  • индекс 1: нормали,
  • index 2: texcoords

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

Если вы скомпилируете эти шейдеры, вы заметите, что первый шейдер ожидает, что позиции в индексе атрибута 0 и нормалях равны 1. Другие будут ожидать положения в 0, но текстурные координаты в 1.

Цитата https://www.opengl.org/wiki/Vertex_Shader:

Автоматическое назначение

Если ни один из двух предыдущих методов не назначает вход для индекса атрибута, тогда индекс автоматически назначается OpenGL, когда программа связана. Указанный индекс является полностью произвольным и может быть различным для разных связанных программ, даже если они используют точный код вершинного шейдера.

Это означает, что вы не сможете использовать ваше VAO с обоими шейдерами. Вместо того, чтобы иметь один VAO на, скажем, объект, вам нужно - в худшем случае - отдельный VAO для каждого объекта за шейдер.

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

(Это не очень большая проблема, если вы не используете отдельные VAO, но все равно можете сделать код более понятным.)


BTW:

При настройке расположения атрибутов для программы шейдера OpenGL вы сталкиваетесь с двумя вариантами

Есть третий вариант в OpenGL/GLSL 3.3: Укажите местоположение непосредственно в шейдерном коде. Это выглядит так:

layout(location=0) in vec4 position;

Но этого нет в шейдерном языке GLSL ES.

Ответ 2

Еще один ответ заключается в том, что glGetAttribLocation возвращает данные вызывающему, что означает, что он неявно требует флеш-конвейера. Если вы назовете это сразу после компиляции своей программы, вы по существу вынуждаете асинхронную компиляцию синхронно выполнять.

Ответ 3

Третий вариант, т.е. layout(location=0) in vec4 position; в шейдерном коде, теперь доступен в OpenGL ES 3.0/GLSL 300 es. Только для входных переменных вершинного шейдера.