Як я можу швидко генерувати підписані поля відстані (2D) у режимі реального часу?


21

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

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

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

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

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

Ось чому мені потрібно це робити в режимі реального часу:

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

Наприклад, порівняно невелика карта розміром 1000 * 256 (ширина * висота) з розміром плитки 10 * 10 пікселів і, таким чином, загальними розмірами 10000 * 2560 пікселів, вже коштувала б вам близько 2 мегабайт, якщо ви виберете порівняно невеликий Роздільна здатність SDF 128x128, припускаючи, що ви зберігаєте лише значення відстані від 0 до 255.

Очевидно, що це може швидко стати занадто великим, і це накладні витрати, які я не хочу мати.

Є ще щось:

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


Я переглянув "що таке підписане поле відстані", і вперше потрапила версія GPU: http.developer.nvidia.com/GPUGems3/gpugems3_ch34.html Це вже трохи старенько, але може допомогти в подальшому пошуку.
Патрік Хьюз

1
Можливо, мені чогось не вистачає, але мене дещо бентежить твердження про те, навіщо це потрібно робити в режимі реального часу (не в останню чергу, чому це позначено спойлерами); по-перше, звідки ви берете цифру 2 Мб для SDF розміром 128x128? По-друге, чому ви вважаєте 2MB особливо великим використанням пам'яті? Я погоджуюсь, що це несуттєво, але, здається, невелика частка вашого загального використання пам'яті карти. По-третє, як генерування поля в режимі реального часу збереже цю пам'ять? Вам все одно потрібно зберігати абсолютно ті самі дані, незалежно від того, чи вони генеруються під час руху або попередньо обчислюються, ні?
Стівен Стадницький

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

1
Якби я генерував поле відстані в режимі реального часу, я створив би ці 2 Мб один раз на кадр (загальний обсяг пам'яті завжди був би пам'яттю, необхідною для одного поля відстані, оскільки мені потрібне лише одне для екрана). Якщо у мене є більша карта, ніж мій приклад 1000x128 (я думаю, що великі карти Terraria виходять далеко за межі 10000-х років), мені потрібна одна з цих 2 Мб для кожної підкарти 1000x128 цієї карти. Чому мені потрібні SDF в першу чергу, описано в першому запитанні, яке я пов’язав на початку цього питання (це стосується тіньового кастингу GPU 2D).
TravisG

1
@heishe Ви намагаєтесь генерувати 2 Мб даних один раз на кадр? Серйозно?
kaoD

Відповіді:


9

Каталін Зіма пояснює, як досягти динамічних 2D-тіней у своїй статті - і він використовує підписане поле відстані (з того, що я можу сказати, що це просто фантазія для тіньового буфера в цьому контексті). Для його методу потрібен графічний процесор, а його реалізація як -не найкраща (його знизилося нижче 60 Гц при приблизно 20 лампах на моїй машині, мій отримав близько 500 ламп); чого можна очікувати, оскільки він віддавав перевагу ясності коду над швидкістю.

Впровадження

Саме так, як він реалізований:

  1. Візуалізуйте всі ролики тіней текстурою.
  2. Обчисліть відстань до центру світла для кожного пікселя та призначте це значення RGB непрозорих пікселів.
  3. Викривіть зображення так, щоб воно відображало, як 3D-камера бачила б ці пікселі.
  4. Наріжте зображення на зображення розміром 2хN, використовуючи незвичайний розмір, описаний у його статті (звичайний розмір не працюватиме).
  5. Зображення 2xN - це ваше підписане поле відстані для всіх чотирьох квадрантів світла (пам’ятайте, що один квадрант - це в основному один кадр камери при 90 градусах).
  6. Надайте світлу карту.
  7. Розмийте світлу карту (виходячи з відстані від світла), щоб ви отримали м'які тіні.

Моя остаточна реалізація була (кожен крок був одним шейдером):

  1. Зробіть (1).
  2. Зробіть (2) і (3) .
  3. Зробіть (4). Його реалізація дійсно повільна: якщо ви можете спробувати використовувати GPGPU для цього. Я не міг використовувати GPGPU (XNA), тому що я зробив:
    • Налаштуйте сітку, де перші N / 2 стовпчики були представлені N / 2 квадратиками з тим самим положенням (що охоплює перший стовпець підсумкового буфера), але відрізняються текстурними координатами (те ж саме для другого N / 2 стовпців)
    • Вимкніть глибинне тестування на GPU.
    • Використовуйте функцію змішування пікселів MIN.
  4. Виконайте (6) і (7).

Це досить геніально: це в основному прямий переклад того, як обробляються тіні в 3D на 2D.

Підводні камені

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


Чи було ваше пристосування до способу зміни розміру єдине, щоб прискорити його, щоб обробити 500 ліхтарів вище 60 кадрів в секунду?
TravisG

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

@heishe стосовно вашого першого питання: не впевнений. Я зробив усі оптимізації за один прохід - я думаю, що пам’ятаю, що вимкнув його і спостерігав, як частота кадрів значно падала. Загальний "загальний" 6 викликів на світло вбиває ваш кадр. Як я вже казав, це схоже, з того, що я можу сказати, у вас на кроці (5) є 4 підписані поля відстані - але хтось, хто знає більше про них, повинен це підтвердити.
Джонатан Дікінсон

Ну, це дуже особливий випадок підписаного дистанційного поля. У звичайному полі підписаної відстані кожен піксель містить відстань до найближчої перешкоди. У цьому алгоритмі поле відстані містить лише одну перешкоду, а також перешкода становить лише 1 піксель у всьому зображенні (джерело світла), тому це поле відстані може генеруватися в O (N).
TravisG

1
@heishe ось мій шейдер: gist.github.com/2384073 . DistortPS - 2 + 3.
Джонатан Дікінсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.