Великий вершинний буфер проти декількох дзвінків дзвінків


14

Я тільки починаю з OpenGL, і я намагаюся використовувати його для створення 2D гри. У цій грі у мене є шестикутна сітка, що складається з дуже великого різноманіття шестикутників різного кольору. Як новачок OpenGL-програміст, я бачу два способи малювання цієї сітки:

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

Який найефективніший метод? Чи є кращий спосіб зробити це?


Ваш попередньо обчислений вершинний буфер повинен лише розширити повз екрана на один шестикутник, потім ви можете підробити його, плавно прокручуючи, поки ви не перейдете повний шестикутник, а потім "перекосити" назад, що стосується кольорів у цьому сценарії, ви можете зберегти 2D текстури на графічному процесорі, прочитайте її у вершинній шейдері та плоско інтерполюйте її у фрагмент шейдера.
MickLH

Проходи зазвичай посилаються на ситуацію, коли одна операція візуалізації спирається на результати попередньої операції. Те, про що ви запитуєте в цьому запитанні, насправді пов’язане зі зменшенням кількості дзвінків на розіграш за один прохід. Я знаю, це звучить педантично, але дуже важливо зрозуміти різницю, інакше багатопрохідні алгоритми не матимуть великого сенсу;)
Андон М. Коулман

@ AndonM.Coleman Хм, дякую, я явно не знайомий з графічною термінологією. Отже, у цьому випадку, як би я це описав? Кілька шейдерів / програмних дзвінків?
Олексій Кінг

Ви можете одразу сказати, що це алгоритм однопрохідного режиму, оскільки немає порядку замовлення; ви можете намалювати ці шестикутники в будь-якому порядку і все одно отримати однаковий результат. Ви можете здійснити кілька дзвінків для зворотного зв'язку, щоб надати OpenGL дані, необхідні для їх надання, але OpenGL фактично вільний їх проводити паралельно, оскільки немає залежностей. Якби він був багатопрохідним , то перед тим, як його можна було намалювати, для шестикутника B може знадобитися результат шестикутника А, або вам може знадобитися намалювати той самий шестикутник кілька разів та поєднати результат.
Андон М. Коулман

Відповіді:


9

Дійсно є кілька способів зробити таку сітку.

Найефективнішим способом було б пристосування. Таким чином, ви робите свій шестикутник лише один раз у VBO, і робите це сто, тисячу чи мільйон разів. Ви можете це зробити вручну, використовуючи шейдери з формою, як ви сказали в пункті 1, але для цього також є вбудована функція OpenGL. Для цього погляньте на glDrawElementsInstanced .

Зауважте, що інстанціювання відбувається швидше, ніж інші методи, якщо ви намалюєте більше певної кількості вбудованих об'єктів. Наприклад, малювання 300 може бути швидшим за допомогою 1 великого VBO, але малювання 2 мільйонів може бути швидшим, якщо ви використовуєте інстальовану візуалізацію.

Якщо ви використовуєте інстальовану візуалізацію, ви можете надсилати дані про об'єкт за допомогою Атрибутів-роздільників . У вашому випадку ви хочете надіслати позицію та колір.

Хороший підручник з інстальованої візуалізації: натисніть

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

Також зауважте, що інстальована візуалізація - це сучасна функція OpenGL, і що для її використання вам доведеться використовувати шейдери. Але завжди краще навчитися це правильно з самого початку.


2
Моменталізація не обов'язково є найбільш ефективною; У багатьох реалізаціях, про які я бачив, підтримка екземплярів застосовувалася для відповідності, але повільніше, ніж окремо малювала багато об'єктів (дійсно, це був лише погано реалізований цикл у драйвері, що робить саме це). Це варіант і хороший, але слід бути обережним для профілю та тестування на цільовій ОС / апараті, перш ніж робити будь-які припущення про "найефективніший".
Шон Міддліч

Домовились. Я бачив, наприклад, різні виступи в Windows / Linux та Ati / nVidia. Дякую за доповнення
Basaa

1
Фактично. Якщо ви намалюєте кілька комбінованих сіток в межах одного vbo (які ділять один і той же простір). Жоден спосіб інстанції не може бути швидшим. Проблема з інстанцією полягає в тому, що вершини не є паралельно обчисленим перехресним екземпляром. Це виключає лише gpu / cpu / gpu sync / drawcall. Тому швидше намалювати один вершинний буфер, що містить 1000 сфер, ніж намалювати 1000 сфер із апаратним інстанцією. (не бракує уваги для усунення фруктів / оптимізація деталей відстані)
Jeroen van Langen

3

Спосіб 1 простіший для кодування і він буде добре, якщо у вас не буде занадто багато шестикутників одночасно. Можливо, ви захочете дотримуватися цього, оскільки ви новачок у OpenGL, щоб уникнути занадто великої складності на вашій тарілці відразу.

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

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