У цій статті я розповім, як створити в UE4 виділення контуру. Як правило, розробники використовуються для цього двома різними способами:
- Рендер сітку двічі. У цьому випадку спочатку рендерится одна сітка (зі стандартним матеріалом), а потім друга (зі злегка збільшеним масштабом і емісійним матеріалом)
- Використовують алгоритм розпізнавання контуру. Він задається в вигляді матеріалу пост-обробки
Основні кроки
Реалізація ефекту виділення контуру у вигляді матеріалу пост-обробки проходить в кілька етапів:
- Створення матеріалу пост-обробки, який виділить контур у об'єктів з увімкненим параметром Render Custom Depth.
- Додавання цього матеріалу пост-обробки в список Blendables, який знаходиться в параметрах блоку Post Process Volume.
- Включення параметра Render Custom Depth у всіх скелетних і статичних сіток, у яких потрібно виділити контур
Карта глибини
У UE4 є відмінна функція, що дозволяє рендерить окремі сітки в окрему карту глибини, а потім використовувати її в матеріалах. Ця карта глибини містить інформацію про дистанцію між кожним пікселем - і в світових координатах, і в поле зору камери. Типова карта глибини виглядає приблизно так:
Наша карта глибини виглядає схожим чином, за винятком того, що в ній видно лише об'єкти, у яких включений параметр «Render Custom Depth»:
створення матеріалу
Найскладніший етап. Ми створимо матеріал, в якому буде реалізований оператор Собеля, згорнутий з кастомной картою глибини. Іншими словами, ми застосуємо на кастомную карту глибини фільтр розпізнавання контуру.
Почнемо з алгоритму згортки. В його основі лежить досить хитромудра математика, але насправді все зводиться до декількох простих кроків
- Беремо піксель P
- Беремо 8 пікселів PN, прилеглих до пікселя P
- Множимо значення в пікселях P і PN на значення в ядрі згортки (тобто робимо 9 умножений)
- Складаємо отримані значення
- повертаємо результат
Спочатку потрібно задіяти карту глибини. Робиться це просто: додайте нод Scene Texture і підключіть його до Emissive Color матеріалу. Також виставте налаштування Scene Texture ID на CustomDepth.
Тепер давайте задіємо прилеглі пікселі. Для цього можна використовувати параметр UVs в ноді Scene Texture. Але проблема в тому, що UV-параметри працюють в текстурних координатах, тобто використовують значення від «0,0» (лівий верхній кут текстури) до «1,1» (правий нижній кут текстури). Тому нам потрібно взяти інвертовані значення висоти і ширини текстури, помножити їх на зміщення від центра осередку (-1, -1), а потім додати до UV-координатами поточного пікселя. Таким чином ми виберемо лівий верхній піксель.
Тепер робимо те ж саме для решти семи прилеглих пікселів. У підсумку розрахунок зміщення для всіх восьми прилеглих пікселів буде виглядати наступним чином:
Отже, у нас є набір UV-параметрів для всіх прилеглих пікселів, тому тепер можна задіяти дані з кастомной карти глибини. Я створив для цього просту функцію матеріалу: в якості вхідних параметрів вона приймає UV-координати, а потім повертає значення обробленого пікселя.
Якщо скористатися цією функцією для обробки даних від прилеглих пікселів, то у нас, власне, будуть всі необхідні дані для розпізнавання контуру. Тепер давайте створимо ще одну функцію матеріалу, яка буде виконувати згортку.
Отже ми зібрали всі шматочки алгоритму. Тепер залишилося лише об'єднати їх усередині підсумкового матеріалу.
В операторі Собеля, по суті, задіяні дві функції згортки: вертикальна і горизонтальна. Ви, мабуть, помітили, що єдина різниця між ними - це вхідні дані про ядро згортки.
Тепер давайте об'єднаємо два цих значення.
ПРИМІТКА: Переконайтеся, що ваш матеріал знаходиться в домені Post Process, а не Surface (мається на увазі «material domain»; це параметр, через який налаштовується, для чого буде використовуватися матеріал). Це можна поміняти в властивості матеріалу.
Налаштування сцени
Тепер, коли матеріал готовий, нам потрібно додати його в список пост-оброблювальні ефектів сцени. Виберіть у своїй сцени блок Post Process Volume і знайдіть пункт Blendables. Додайте до списку Blendables новий компонент, а потім виберіть зі списку створений нами матеріал. Якщо блоку пост-обробки у вашій сцені немає, створіть його. Також переконайтеся, що у блоку Post Process властивість Unbound виставлено на «true». В іншому випадку гравець буде бачити ефект рядки тільки в тому випадку, якщо буде перебувати всередині блоку Post Process Volume.
Щоб перевірити результат, помістіть в сцену якусь сітку і включіть в неї параметр Render Custom Depth.
Я налаштував сцену таким чином, що ефект рядки буде з'являтися у статичної сітки тільки в тому випадку, якщо гравець наведе на неї приціл. Я вирішив скористатися шаблоном для FPS. Крім того, я додав у блюпрінт MyCharacter функцію Trace. Вона викликається таймером, цокають кожні 0,1 секунди, і перевіряє, чи дивиться гравець на статичну сітку. Якщо дивиться, параметр Render Custom Depth виставляється на «true». Якщо гравець перестає цілитися в сітку, значення в змінній Render Custom Depth змінюється на «false». Подивитися, як це все працює, можна в файлі, посилання на який можна знайти нижче, в розділі «Завантаження».
- Тут можна завантажити матеріал з ефектом виділення контуру, створеним за інструкціями цього керівництва.
- Тут можна завантажити проект, в якому використовується цей ефект.
Оригінал можна прочитати тут.