2D ігри та сучасний OpenGL


10

Попередні поняття

Добре, так що я зібрав поки що це:

  • не використовуйте фіксований трубопровід (застарілий або буде застарілий)
  • vbos зберігає "об'єктні моделі" (здебільшого n вершинних даних)
  • vaos описує, як складаються дані, щоб малювати дзвінки знали, яка частина кожної Vbo є для того, яка інформація про вершину (один vao може посилатися на кілька vbos, навпаки - це щось важко)
  • кожен дзвінок дзвінка також надсилає вершинні дані в шейдери

Як я бачу 3D (необов’язково)

З огляду на ці відомості, я бачу, як малювати складні об'єкти 3D дуже добре із сучасним OpenGL. Ви в основному завантажуєте купу моделей об'єктів (можливо, з Blender або іншого подібного програмного забезпечення) у VBO з локальними координатами, а потім просто надаєте для кожного примірника об'єкта інший параметр шейдера (зміщення) для виведення у світовий простір.

Проблема / питання

Однак у 2D проблеми та пріоритети зовсім інші. Ви не малюєте багато складних об'єктів, вам не потрібні складні матриці проекцій, а що-небудь і шейдери набагато простіші.

Який був би найкращий спосіб малювати часто (насправді часто, в основному кожен кадр) змінюючи геометрію за допомогою сучасного OpenGL?

У наступному параграфі ви можете побачити деякі ідеї проблем (проблема кола та прямокутника), які краще визначити вид змін, які мене цікавлять.

Мої спроби (необов’язково)

Отже, я почав думати, як би я мав справу з малюванням основної 2D геометрії на екрані:

  • квадрат: завантажте [(1, 0), (1, 1), (0, 1), (0, 0)]VBO для геометрії квадрата в локальному просторі, а потім надайте шейдеру фактичну ширину квадрата та світові координати та кольорову інформацію

охолоджується, виглядає легко. Перейдемо до кола:

  • коло: вентилятор трикутника з ... е. скільки точності (кількість вершин)? для малих кіл точність повинна бути невеликою, а для кіл помилок - точність. Очевидно, що завантаження 1 VBO не може відповідати всім випадкам. Що робити, якщо мені потрібно додати точність, оскільки розмір кола має бути більшим?

Менш круто. Перейдемо до чогось легшого, прямокутника:

  • прямокутник: е. немає "загальної геометрії прямокутника". У вас просто пропорція ширини / висоти, і все, але, мабуть, кожен прямокутник відрізняється, якщо розмір змінюється.

Як бачите, звідти справи йдуть під гору. Особливо зі складними багатокутниками та ще.

Ніякої політики коду: P

Мені просто потрібен огляд ідеї, ніякий код не потрібен, особливо код C або C ++. Просто скажіть такі речі, як: "зробіть VBO з даними вершин, а потім зв’яжіть його, ...".


Я думаю, я розумію, що ви запитуєте, але ви, можливо, захочете дати цьому питанню трохи більше напряму. Трохи незрозуміло, про що питають - що насправді є тісною причиною.
Лисоль

@AidanMueller Я не впевнений, що ти маєш на увазі, але сміливо дай більше напрямків, якщо ти відчуваєш потребу.
взуття

Зараз найвища відповідь починається з того, що "Ви, здається, головне питання". Це вказує на те, що незрозуміло, про що ви питаєте. Можливо, вам слід дати резюме того, що вам не потрібно знати в кінці запитання. Це питання / питання, а не дискусія.
Лисоль

@AidanMueller Я не вважаю цього контексту. У ній написано: "Здається, ваше головне питання ...", а потім він / вона цитує питання, яке я розмістив. Що насправді вказує на те, що це досить зрозуміло, щоб бути цитованим. Крім того, фраза вказує не на те, що моє запитання є незрозумілим, а є основне питання та ще одне другорядне питання (а саме: яке рішення конкретних випадків я представив). Я справді не бачу проблеми з моїм поточним запитанням, і, мабуть, навіть не відповідав, оскільки я вважав обидві відповіді дуже корисними і суттєвими.
взуття

Ви можете намалювати точне коло за допомогою фрагмента шейдера.
користувач253751

Відповіді:


5

Здається, ваше головне питання :

Який був би найкращий спосіб малювати часто (насправді часто, в основному кожен кадр) змінюючи геометрію за допомогою сучасного OpenGL?

У більшості способів немає великої різниці між 2d і 3d OpenGL. Графічний конвеєр має одну додаткову координату, Z, яка не буде використовуватися стільки в 2d, але це приблизно так.

Існує кілька способів зміни геометрії на кожному малюнку.

  • Ви можете висувати нові вершини, надані процесором, кожен кадр. (Див. Https://stackoverflow.com/questions/14155615/opengl-updating-vertex-buffer-with-glbufferdata для деяких приміток про повторне використання буферів.)

  • Ви можете намалювати різні частини наявного буфера, за допомогою glDrawArrays(mode, first, count). Якщо цикли анімації, можливо, ви можете помістити попередньо обчислені кадри з різними списками вершин в один великий буфер і намалювати відповідну частину буфера в кожному кадрі.

  • Ви можете впливати на список вершин за допомогою деяких інших даних, наприклад, рівномірного масиву чи текстури. У своєму вершинному шейдері прочитайте ці дані та застосуйте їх відповідним чином. Це лише інші ідіоми для подання даних в GPU, і, ймовірно, не матиме великої різниці у продуктивності.

  • Якщо у вас є багато примірників однієї геометрії (можливо, це впливає на атрибути), то це glDrawElementsInstanced()може бути корисним

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

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

В цілому, я б сказав: "Комп'ютери швидкі, змушуйте його працювати найпростіше, можливо, встановивши свіжі вершини, створені процесором, кожен кадр. Потім, подивіться, чи це досить добре. Профілюйте акумулятор / процесор. по-перше, слід пам'яті другий ".

Ваше інше запитання , перефразоване, "Який хороший спосіб малювати кола та прямокутники?"

Кола.

  • За допомогою тесселяційних шейдерів (або геометричних шейдерів) ви можете зробити свою геометрію динамічною.

  • Ви можете намалювати квадрати, а у вашому фрагменті шейдер лише непрозорий (альфа = 1,0) у радіусі та прозорий (альфа = 0,0) поза радіусом. Тоді це піксель ідеально кожен раз. (Зробіть свої квадратні вершини від -1 до +1, а в фрагменті шейдер щось подібне outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;. Можливо, також трохи згладити край, там буде добре виглядати ...)

  • Ви завжди можете використовувати, скажімо, вентилятор з трикутником на 120. Напевно, досить добре.

Прямокутники.

  • Я думаю, ти відповів на власне запитання з цього питання. Те, що ви запропонуєте, буде добре працювати!

Фрагмент-шейдер / радіус досить акуратний, дякую. Що стосується того, що я відповідаю на власне запитання, я не думаю, що я розумію, що ти маєш на увазі.
взуття

О, так само, як і з квадратом, ви згадуєте про контроль ширини (з рівномірним, я припускаю), і ви написали: "Ви просто маєте пропорцію ширини / висоти, і все, але кожен прямокутник, мабуть, відрізняється, якщо розмір змінюється" . Отже, для прямокутника зробіть те саме, що і квадрат, але вам знадобиться 4 значення (x, y, w, h) замість 3 (x, y, w). Або передайте (xlow, xhigh, ylow, yhigh) як чотири уніформи. З вашим входом (від 0,0) до (1,1), цього достатньо, щоб вершина шейдера зробила все, що потрібно.
Девід ван Брінк

О, я бачу, це має сенс.
взуття

Чи є в сучасних GL автоматичний вентилятор, як GL_TRIANGLE_FAN, від трубопроводу з фіксованою функцією?
Джон П

5

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

1) Квадрати і прямокутники досить прості. У мене є лише одна коробочка 1x1 у VBO, яку я використовую для того, щоб заскрити все. Я передаю матриці MVP в шейдер із цим «блоком одиниць», і я поєднав його з додатковим масштабуванням, щоб масштабувати поле до правильних розмірів - як відомо, ви можете мати різну шкалу x і y.

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

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

Підключаючи дані VBO до атрибутів шейдера, я використовую glVertexAttribPointer. Він має параметр stride, призначений для використання для переплетених даних (якими я користуюсь). Але можливо використовувати його так:

glVertexAttribPointer(..., n * sizeof(VERTEX_DATA), ...);

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

Взагалі, так, робота з VBO та подібними процесами робить налаштування на стороні процесора дещо складнішим, чому я вивчав різні речі, щоб зробити налаштування на стороні GPU (шейдери). Однак, згідно з цією статтею, використання VBO є більш ефективним для сучасного обладнання, навіть якщо вам потрібно багато "втручання" на стороні процесора:

http://www.quelsolaar.com/opengl_performance.txt

Сподіваюся, це допоможе вам трохи розробити та визначити свої напрямки.


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