Явне проти автоматичного прив'язки розташування атрибутів для шейдерів OpenGL


83

Налаштовуючи розташування атрибутів для програми шейдерів OpenGL, у вас є два варіанти:

glBindAttribLocation () перед посиланням для явного визначення розташування атрибута.

або

glGetAttribLocation () після зв’язування для отримання автоматично присвоєного розташування атрибута.

Яка утиліта для використання одного над іншим?

І якому з них, якщо такий є, є кращий на практиці?


6
Я не заважав використовувати glBindAttribLocationсвій графічний движок, який чудово працював на Linux. Коли я переносив у вікна, він використовував мої нормалі як вершини - я повинен був чітко вказати йому порядок змінних у моєму шейдері, glBindAttribLocationщоб він працював ...
Джарретт,

Відповіді:


93

Я знаю одну вагому причину віддавати перевагу чіткому визначенню місця розташування.

Вважайте, що ви зберігаєте дані геометрії в об’єктах масиву Vertex. Для даного об’єкта ви створюєте VAO таким чином, щоб індекси відповідали, наприклад:

  • індекс 0 : позиції,
  • індекс 1 : норми,
  • індекс 2 : текстові слова

Тепер подумайте, що ви хочете намалювати один об’єкт двома різними шейдерами . Один шейдер вимагає як вхідних даних положення та звичайні дані , інший - положення та текстурні координати .

Якщо ви скомпілюєте ці шейдери, ви помітите, що перший шейдер очікує позицій з індексом атрибутів 0 і нормалей на 1. Інший очікує позицій на 0, але текстурні координати на 1.

Цитування https://www.opengl.org/wiki/Vertex_Shader :

Автоматичне призначення

Якщо жоден із попередніх двох методів не призначає вхідні дані індексу атрибутів, тоді індекс автоматично призначається OpenGL, коли програма пов’язана. Присвоєний індекс є абсолютно довільним і може бути різним для різних зв'язаних програм, навіть якщо вони використовують однаковий код вершинного шейдера.

Це означає, що ви не зможете використовувати свій VAO з обома шейдерами. Замість того, щоб мати один VAO на, скажімо, об’єкт, вам знадобиться - у гіршому випадку - окремий VAO на об’єкт на шейдер .

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

(Це насправді не є великою проблемою, якщо ви не використовуєте окремі VAO, але все одно можете зробити свій код зрозумілішим.)


ДО:

Налаштовуючи розташування атрибутів для програми шейдерів OpenGL, у вас є два варіанти

У OpenGL / GLSL 3.3 є третій варіант: вкажіть місце безпосередньо в коді шейдера . Це виглядає так:

layout(location=0) in vec4 position;

Але цього немає в мові шейдерів GLSL ES.


1
Я не бачу сенсу. VAO дуже легкі, і ви, як правило, відтворюєте їх для кожного кадру. У вашому випадку ви просто створили б різні VAO перед викликом кожного шейдера, чи не так?
PierreBdR

1
Так, ви можете це зробити, звичайно. Це буде працювати так само добре, ми тут лише обговорюємо конвенції. :)
Кос

4
Третій варіант насправді доступний у GLES2.0, але формат дещо інший: атрибут layout (location = 0) vec4 position; Зверніть увагу, що це вам також знадобиться у верхній частині вашого файлу GLSL: #extension GL_EXT_separate_shader_objects: enable
Gavin Maclean

35
"VAO насправді легкі, і ви, як правило, відтворюєте їх для кожного кадру. У вашому випадку ви просто створили б різні VAO, перш ніж викликати кожен шейдер, чи не так?" - Ні, ви зазвичай цього не робите, оскільки це врешті-решт повністю знецінює цілі VAO. Навіщо тоді взагалі використовувати VAO?
Крістіан Рау,

2
Просто примітка. Ви не зможете зберігати дані геометрії у VAO. Це було б у VBO. VAO не мають сховища даних.
середній Джо

20

Інша відповідь тут полягає в тому, що glGetAttribLocation повертає дані абоненту, що означає, що він неявно вимагає очищення конвеєра. Якщо ви викликаєте це відразу після компіляції програми, ви по суті змушуєте асинхронну компіляцію відбуватися синхронно.



Дякую, це дуже важлива думка.
Jing

1
Я розумію, що в більшості ситуацій вам все одно доведеться телефонувати glGetUniformLocation; чи це конкретне врахування досі є актуальним?
Mike Weir

@MikeWeir, починаючи з GL 4.3, ви можете встановити чітке єдине розташування .
Руслан

1
@Ruslan Вони використовують OpenGL ES.
Mike Weir

9

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


7
Як вони натякають, картки Intel можуть цього не підтримувати (хоча, як я розумію, це ідеально комфортно 3.0+), що огидно :)
mlvljr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.