Чи слід від’єднувати буфери?


12

Я робив кілька тестів з OpenGL ES 2 і отримав кілька запитань, моя поточна програма така:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

Проблема

Даний збій коду, після деяких досліджень, я зрозумів, чому: мені потрібно відв’язати свій індексний буфер в init частині (після "заповнення індексу буфера glBufferData") або відв'язати його перед першим "Зв'язати VAO"

Мої запитання:

  • Чи можу я помістити свій індексний буфер у VAO (VAO фондовий буфер?)?
  • Чи потрібно було відміняти буфери після кожного оновлення (glBufferData)?

У своїй програмі у мене є кілька буферів, які оновлюються на кожному кадрі (наприклад, Частинки), тому у мене є стек OpenGL таким чином:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

Перші 3 рядки оновлюють буфер Vertex, два останні об’єкти малювання, які мають бути чимось таким:

-> bind buffer 1
-> update buffer 1
-> draw

Дякую

Відповіді:


12

Ви, здається, багато робите над непотрібним прив'язкою / розв’язуванням. Якщо ви використовуєте VAO, то слід прив'язувати VAO лише тоді, коли ви його налаштовуєте та коли малюєте геометрію. Ви знову прив'язуєте VBO / IBO лише тоді, коли вам потрібно оновити їх.

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

Тепер, беручи за собою кулакову послідовність операцій, це загальний порядок, який я б очікував побачити:

На init:

  1. Створіть і зв’яжіть VAO. Будь-які VBO та IBO, які ви пов'язуєте в послідовності, будуть асоційовані з поточним VAO (цим).

  2. Створення та зв’язування буфера індексів.

    • Заповніть індексний буфер glBufferData/glMapBuffer.
  3. Створення та зв’язування вершинного буфера.

    • Заповніть вершинний буфер glBufferData/glMapBuffer.
  4. Налаштування атрибутів вершин за допомогою glEnableVertexAttribArray/glVertexAttribPointerтощо.

  5. За бажанням від'єднайте все, щоб уникнути випадкових змін буферів та VAO. Не забудьте спочатку від’єднати VAO . Наприклад:glBindVertexArray(0);

На розіграші:

  1. Якщо тільки малювати буфери :

    • Зв’яжіть ВАО;
    • Виконайте розіграші (розіграші).
  2. Якщо оновлення та малювання :

    • Пов'язують VAO, VBO, IBO;
    • Оновити буфери (оновлення атрибутів вершин необхідне лише в тому випадку, якщо формат вершин змінився);
    • Виконайте розіграші (розіграші).
  3. Необов'язково від’єднувати, щоб уникнути випадкових модифікацій буферів та VAO.

Це так просто. Цей порядок операцій повинен функціонувати без проблем.


2
Я хотів би додати, що в своїх експериментах (2014 р.) Із реальними випадками життя (але простими шейдерами, щоб не бути вузьким місцем у графічному процесорі), я виявив, що покращення продуктивності використання VAO є незначним (<2% економії процесора) після належного замовлення рендеринг-дзвінків був реалізований для повного пропуску налаштування VBO при використанні того ж VBO для послідовних викликів візуалізації (від 10 до 33% економії процесора), і я потрапив на деякі помилки драйверів з VAO, тому я в кінцевому підсумку відключив їх за замовчуванням. Це було ще менш значним при використанні складних шейдерів, MSAA тощо, що вузьке місце в GPU залишає процесор простою в очікуванні навіть на мобільному пристрої.
Стефан Хокенхолл

2
Зауважте, що неправильне вирівнювання даних вершин таким чином, що не підтримується апаратним забезпеченням, змусить драйвери GPU переупорядкувати дані VBO під час кожної установки, тоді як драйвери можуть переупорядкувати їх один раз з VAO, доки нічого не буде змінено таким чином YMMV. Найкраще будь-коли вирівняти дані та вершини майданчика.
Стефан Хокенхолл

1
Чому VAO має бути незв'язаним перед усім іншим?
Даніель Сафарі

@DanielSafari, ти маєш на увазі після налаштування? Якщо ви спочатку від'єднаєте буфер (буфер зв'язування 0 / null), буде зрозуміло, що точка зв'язування в поточному VAO. Тому спочатку слід встановити нульовий VAO.
гламперт

@glampert - ні, це не так, як працюють прив'язки; прив'язка буфера використовується, коли викликається glVertexAttribPointer, а не інакше (виняток: GL_ELEMENT_ARRAY_BUFFER). Зміна прив'язки буфера після виклику glVertexAttribPointer не впливає.
Максим Мінімус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.