Високопродуктивна система освітлення для 2D-ігор



Привіт, мене звуть Александер Бирці (Alexander Birke), нещодавно я видав свою першу гру у Steam під назвою Laser Disco Defenders. Мені здається, було б цікаво розкрити деякі технічні та дизайнерські рішення, що увійшли в гру. Почну з власної системи освітлення, що дозволяє працювати з безліччю двомірних джерел світла навіть на слабких комп'ютерах. LDD створена в Unity, але цей підхід спрацює в будь-якому іншому ігровому движку, що дозволяє створювати процедурні сітки (meshes).

4 МБ епілептичних gif


Чому саме власна система освітлення?
Основна механіка LDD полягає в тому, що кожен вистрілено лазерний промінь продовжує відбиватися від стін і може потрапити в гравця, тому ми назвали це "bullet hell своїми руками". Візуальний стиль надихався епохою диско і яскравими танцполами того часу, тому я хотів, щоб лазери могли висвітлювати оточення. Освітлення також корисно, так як допомагає гравцеві зрозуміти, що скоро в кадр потрапить лазерний промінь. Гра була випущена ще і на PlayStation Vita, тому мені потрібно було більш продуктивне рішення у порівнянні зі стандартним відкладеним освітленням (deferred lighting) Unity, використовують виклик відтворення для кожного джерела світла, отрисовываемого в сцені. На екрані одночасно запросто може бути до 30 лазерних променів, з таким навантаженням портативна консоль не впорається. Ще я хотів, щоб освітлення відповідало формі лазерних променів. Лазерний промінь зазвичай довгий і тонкий, тому ні один із стандартних джерел освітлення Unity (direction, point, spotlight) не підходив.


Точкове джерело зліва не відповідає формі лазерного променя. Праворуч — потрібний контур світла.

Інші ігрові елементи теж повинні були випромінювати світло, тому мені потрібен був простий компонент освітлення, розміщений на ігрові об'єкти, що система освітлення повинна була рендери.


Повинні підтримуватися не тільки лазерні постріли, але й інші джерела світла.

Процедурні сітки йдуть на допомогу!
Основна ідея використання процедурних сіток полягала у «вдруковуванні» даних про висвітлення в буфер освітлення, який потім сэмплировался в шейдери. Це не відрізняється від принципу роботи відкладеного освітлення, однак для мого рішення потрібна робота тільки в 2D, тому я міг розрахувати всі освітлення за один прохід відтворення завдяки візуалізації освітлення з допомогою процедурної сітки.

Лазери в грі рендерились як процедурна сітка, тому у мене вже була текстурою, яку можна використовувати для зберігання зменшення інтенсивності світла. Я назвав її (пам-пам-па-а-ам!)… лазерної таблицею!


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

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


Схема генерування сітки для окремого променя. Для кожного сегмента потрібні два чотирикутника (quad) решт променя і ще один для прямого сегмента посередині. Світла від світла стіни теж потрібен свій quad. Така топологія використовується для відтворення самого лазера.

Для створення освітлення кожного лазера я беру положення кожного сегмента і раздвигаю їх вершини назовні, залежно від того, наскільки далеко світло може поширюватися від лазера. Потім створюються і додаються до сітки вершини для інших джерел світла. У LDD мені потрібні були тільки круглі джерела, але можна легко додати і інші форми. У цих круглих джерелах використовується таке ж дифузне світіння з лазерної таблиці і рендерится як чотирикутники.




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

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




Сітка освітлення і текстура, на яку вона рендерится.

Після цього колірної буфер відправляється в графічний процесор як звичайна текстура, тому може використовуватися з будь-якого шейдера. Були створені власні шейдери для спрайтів, часток і всього іншого, що вимагає освітлення. У вершинном шейдере кожна вершина визначає положення свого viewport, тому може використовуватися як UV-координати при сэмплировании текстури освітлення в шейдере фрагмента. Найцікавіше — це фони гри. У них використовується альфа-канал для визначення величини отражаемості конкретного текселя. Це дуже допомагає додати в гру більше глибини.


Приклад фонової текстури в Laser Disco Defenders. Зліва показано колірні канали, праворуч — альфа-канал, що використовується для отражаемості, що забезпечує створення темних тріщин на тій текстурі печери. Там ще є скелет космічного кита… просто тому що ми можемо!

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

Висновок і подальша робота
На консолі Vita гра забезпечує пристойну кількість FPS, ніж я дуже гордий, враховуючи візуальну чіткість гри. Хороший рівень продуктивності був відзначений і в оглядах гри для ПК. Сподіваюся, ви теж погодьтеся, що освітлення значно посилює психоделічний диско-стиль гри.
Система поки обмежена тим, що не може створювати тіні. Ви можете додати їх, але ціною продуктивності. Якщо ви вирішите зробити тіні, вам, швидше за все, не вдасться провернути фокус з буфером освітлення низького дозволу. Ще система не може забезпечити відображення освітлення. Їх можна створити за допомогою ще однієї лазерної таблиці, що використовує колірні канали, що представляють напрямки, які потім «впечатываются» в окремий буфер напрямків, але така система вже складніше того, що мені потрібно було для Laser Disco Defenders.

Сподіваюся, вам сподобалася стаття. В наступному пості я буду детально розглядати процедурну генерацію рівнів, так що залишайтеся з нами!

Александер управляє бристольської ігровою студією Out Of Bounds Games. Ви можете підписатися на його Twitter або сторінку в Facebook компанії з найбільшим корпоративним URL в світі. Ще він організовує Bristol Unity Meetup.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.