Який стан зберігається в об’єкті OpenGL Vertex Array (VAO) і як правильно використовувати VAO?


25

Мені було цікаво, який стан зберігається в VAGL на OpenGL. Я зрозумів, що VAO містить стан, пов’язаний із специфікаціями вершин буферизованих вершин (які атрибути є у буферах та які буфери пов'язані, ...). Щоб краще зрозуміти правильне використання VAO, я хотів би точно знати, який стан вони мають.


Як я вважаю, слід використовувати VAO

З простих прикладів я зрозумів, що правильне використання VAO полягає в наступному:

Налаштування

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

Візуалізація

Bind VAO
---- Draw
Unbind VAO

З цього я припускаю, що принаймні прив'язки буфера вершин та специфікації атрибутів вершин зберігаються у VAO. Однак я не впевнений, як ця схема використання поширюється на ситуації, коли (кілька) текстур і (кілька) шейдерних програм вступають у гру. Чи зберігається програма активного шейдера у VAO? А чи зберігаються текстури прив'язки текстури (з їх параметрами вибірки / обгортання ) в VAO? Ditto для уніформи ?


Тому мої запитання:

  • Який точний стан зберігається у OpenGL VAO ? (Прив'язки VBO, характеристики атрибутів, активна програма шейдера, прив'язка текстури, налаштування вибірки / обгортання текстури, уніформа ...?)
  • Як я можу правильно використовувати VAO в більш складних налаштуваннях візуалізації, де (кілька) текстур із відповідними налаштуваннями вибірки / обгортання, (декілька) програм шейдерів та уніформи?

1
VAO зберігає дані про вершинні місця розташування атрибутів. Він також зберігає ідентифікатори VBO, в яких ці атрибути містяться. Вам не потрібно прив'язувати VBO, коли щось малюєте, його потрібно прив’язати перед викликом glVertexAttribPointer () під час створення VAO.
HolyBlackCat

Відповіді:


18

VAO зберігає дані про вершинні місця розташування атрибутів. (І деякі інші пов’язані з ними дані.)
"VBO bindings, active shader program, texture bindings, texture sampling/wrapping settings, uniforms"Абсолютно не пов'язані з цим.

Ви можете запитати, чому він не пам'ятає прив'язку VBO. Оскільки вам не потрібно прив'язувати VBO, щоб щось намалювати, його потрібно прив’язувати лише під час створення VAO: Коли ви телефонуєте glVertexAttribPointer(...), VAO запам'ятовує, що VBO в даний час пов'язане. І VAO буде приймати атрибути з цих VBO, коли ви малюєте їх, навіть якщо ці VBO не пов'язані в даний час.


Також VAO та VBO повинні використовуватися незначно по-різному:

Це не вийде

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

тому що вам потрібно прив’язати VBO, щоб вказати місця атрибутів.

Отже, ви повинні зробити це так:

Generate VAO
BindVAO
Generate VBO's
BindVBO's
Specify vertex attributes

Ви можете змінювати дані VBO коли завгодно, але їх потрібно зв’язати раніше.

І малюнок повинен виглядати так:

Bind VAO
Draw


Як ви могли помітити, я видалив unbindдзвінки з ваших списків. Вони майже повністю марні, і вони трохи сповільнить вашу програму, тому я не бачу причин їх телефонувати.


9
"тому я не бачу причин називати їх". щоб не допустити випадкових змін. Особливо проблема при використанні сторонніх бібліотек.
храповик виродка

Дякую за чудову відповідь! Отже, коротше кажучи, VAO зберігає лише атрибути вершин. При зв'язуванні VAO VBO не відновлюються, оскільки VAO знає, в яких буферах знайти атрибути. Усі інші стани містяться у глобальному стані OpenGL.
Jelle van Campen

@JellevanCampen Так, правильно. FYI, він також зберігає вимкнути / увімкнути стан атрибутів ( gl{Enable|Disable}VertexAttribArray()), їхніх значень за замовчуванням ( glVertexAttrib*()), режиму інстанції ( glVertexAttribDivisor()) та, ймовірно, чогось іншого.
HolyBlackCat

@HolyBlackCat Ви впевнені, що стан за замовчуванням (glVertexAttrib ()) є частиною стану VAO? Вікі OpenGL стверджує інакше, кажучи, що вони є контекстним станом.
rdb

@ndb Nope, я не впевнений. Я очікував, що вони будуть частиною штату VAO, і я цього не перевіряв.
HolyBlackCat

4

Він зберігає лише прив'язку вершин та прив’язку буфера до індексу

Це всі параметри glVertexAttribPointerплюс буфер, прив’язаний до Vertex_Array_buffer під час виклику glVertexAttribPointerта пов'язаного Element_Array_buffer.

Уніформа - частина поточної програми.

Все інше - глобальна держава.

Ви сумніваєтесь, що ви можете перевірити таблиці стану у специфікації використовуваної вами версії.


Дякую також за відповідь! Це очищає речі для мене.
Jelle van Campen

4

Ось просте, але ефективне пояснення: в основному буферний об'єкт містить інформацію, яку можна інтерпретувати як просто біти необроблених даних, які самі по собі нічого не означають, тому НАСТІРНО дані, які можна подивитися будь-яким способом дійсно

i.e float vbo[]={1.0,2.0,34.0...}

і спосіб, по якому OpenGL був розроблений, полягає в тому, що ви повинні ВИЗНАЧИТИ, як виглядатимуть дані, які будуть переходити до різних шейдерів, до шейдерів

в тому, що ви також повинні визначити, як він буде читати ці дані, у якому форматі вони є, і що з ними робити, і як вони будуть використовуватися, і для чого вся ця інформація зберігається у VAO

наприклад, ви можете оголосити дані, які зберігаються в масиві, як це float vbo = {11.0,2.0,3.0,4.0}

що потрібно далі на цьому етапі - як інтерпретувати ці дані з VBO в VAO, і що це означає, це наступне

VAO можна встановити для зчитування 2 поплавків на вершину (це зробило б це 2 вектори з двома розмірами x, y) або ви можете сказати vao інтерпретувати його як 1 вектор з 4 вимірами, тобто x, y, z, w тощо

але також інші атрибути цих даних визначаються і зберігаються у VAO, такі як формат даних (незважаючи на те, що ви оголосили масив float, ви можете сказати шейдеру, щоб він прочитав його як ціле число, звичайно система перетворює необроблені дані в процес від float до цілого числа і має свій набір правил, що робити в таких умовах)

Тому в основному VBO - це дані, а VAO зберігає, як інтерпретувати ці дані, тому що шейдери та сервер OpenGL розроблені дуже нудно, і потрібно знати все, перш ніж він вирішить, як їх обробити і що з ним робити і де викласти

звичайно, це насправді не носить, він насправді виглядає найефективнішим, оскільки йому потрібно зберігати ці дані в пам'яті графічного сервера, щоб отримати найбільш ефективну та швидку обробку (якщо тільки не вирішить, що цього не потрібно робити, якщо дані не повинні оброблятися таким чином і використовуватись для іншої інформації, до якої часто не можна отримати доступ), а отже, чому деталі, що робити з даними та як їх обробляти, потрібно зберігати в VAO, так VAO - це як заголовок, а VBO - як чисті необроблені дані, які заголовок використовує та визначає (у цьому випадку переходить до атрибутів вершини шейдера) за винятком того, що VBO не обмежується лише тим, що використовується одним VAO, може бути використаний і повторно використаний і пов'язаний з багатьма VAO, наприклад:

що ви можете зробити, ви можете прив’язати один буферний об’єкт до VAO1, а також (окремо) прив'язати один і той же буферний об’єкт до VAO2, кожен інтерпретуючи його по-різному, так що якщо ваш шейдер, де обробляти дані, залежно від того, який VAO є тим, що є Зв'язане воно оброблятиме ті ж самі необроблені дані по-різному до фрамбуферу (малювання пікселів до вікна), що призводить до різного відображення одних і тих же даних, що базуватиметься на тому, як ви визначили його використання в VAO


Це найкраща відповідь!
CodingMadeEasy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.