Як я можу швидко генерувати підписані поля відстані (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.