Unreal Engine 4: Сел-Шейдинг
В этом занятии, посвященном Unreal Engine 4 вы узнаете, как использовать материалы постобработки для создания шейдера типа cel.
Благодаря физическому рендерингу в Unreal Engine 4 можно довольно просто создать реалистичную графику. Этот инструмент позволяет настроить мельчайшие детали, плоть до настройки отбликов света на том или ином объекте. Однако, если вы хотите разработать игру со стилизованным внешним видом, вам также необходимо изучить другие приемы.
Один из способов получить стилизованный вид — использовать затенение cel (которое также известно, как затенение toon).
Эта техника имитирует затенение и как правило используемое в мультфильмах и аниме. Примером могут служить такие игры как Jet Set Radio, The Legend of Zelda: The Wind Waker и Gravity Rush.
В этом уроке вы научитесь:
- Создавать и использовать материал постобработки;
- Создавать шейдер типа cel;
- Использовать шейдер типа cel с конкретными сетками;
- Управлять цветными полосами, используя таблицы поиска.
Примечание: Предполагается, что вы уже знаете основы использования Unreal Engine, однако если вы забыли какую-то информацию или один из пунктов вам покажется непонятным, то вы можете ознакомится с серией уроков, посвященных изучению Unreal Engine для начинающих.
Это руководство является первой частью серии, посвященной шейдерам в Unreal Engine:
- Часть 1: Сел-Шейдинг (вы здесь!)
- Часть 2: Toon Контуры
- Часть 3: Пользовательские шейдеры с использованием HLSL
- Часть 4: Фильтр цветовой гаммы
Введение
Скачайте материалы, которые вам понадобятся в ходе этого занятия. Разархивируйте файл и откройте CelShader.uproject. Вы должны увидеть следующую сцену:
Это персонаж, которого вы будете затенять, однако прежде чем начать, необходимо понимать, что такое сел-шейдинг.
Что такое Сел-Шейдинг?
Затенение Cel используется в случае, если в процессе визуализации объекта, используя несколько цветных полос, вместо непрерывного градиента.
Ниже приведен пример затенения персонажа в аниме «Легенде о Зельде: Дыхание дикой природы». Обратите внимание, что только эльф имеет затенение типа cel, тогда как фон — нет.
На этом изображении используются три полосы: одна для теней, одна для средних тонов и одна для светлых тонов.
Распространенным заблуждением является то, что если что-то имеет очертания, оно обязательно должно быть затенено цветом. Опровержением является графика игры Borderlands. Не смотря на то, что эта игра имеет стилизованный вид, в ней нет эффекта затенения. Посмотрите на изображение ниже — в затенении персонажа не используются цветные полосы:
Несмотря на то, что контуры не являются штриховкой, их часто объединяют, чтобы изображение выглядело так, как будто оно нарисовано. Этот прием встречается во многих играх в стиле аниме, таких как Guilty Gear Xrd и Dragon Ball FighterZ:
Метод сел шейдинга
Наиболее распространенным методом является сравнение направления поверхности (известного как нормальное) и направления света. Рассчитав точечное произведение между этими двумя направлениями, вы получите значение в диапазоне от -1 до 1.
Значение -1 означает, что поверхность и свет направлены в разные стороны; 0 означает, что они перпендикулярны друг другу; 1 означает, что они смотрят в одном направлении:
Устанавливая пороговое значение, вы можете создать сразу несколько полос. Например, вы можете назначить более темный цвет, если значение точечного объекта больше -0,8. Если скалярное произведение меньше -0,8, такому объекту присваивается светлый цвет. Таким образом создается двухполосный шейдер типа cel:
Недостаток этого метода заключается в том, что другие источники света не могут влиять на объекты, затененные в cel. Кроме того, объекты также не могут отбрасывать тени на уже затененные объекты:
Чтобы это исправить, вам необходимо использовать другой метод. Вместо вычисления точечного произведения вы рассчитываете освещенность поверхности, а затем это значение можно использовать во время установления порога значений вместо расчета точечного произведения:
Создание сел шейдинга
В этом занятии затенение типа cel является эффектом постобработки, которая позволяет изменить изображение после того, как движок завершит его рендеринг. Обычно в постобработке используются изменение резкости, размытие движения и цветовой гаммы.
Чтобы создать собственный эффект постобработки, вам нужно использовать отдельный материал постобработки. Для этого перейдите в папку Materials и создав новый материал, переименуйте его в PP_CelShader и откройте.
Для преображения обычного материала в материал постобработки, необходимо изменить его параметр domain. Перейдите на панель Details и измените поле Material Domain на Post Process:
Первый шагом в создании шейдера типа cel является вычисление освещения каждого пикселя изображения — назовем это буфером освещения.
Расчет буфера освещения
Когда Unreal отображает изображение на экране, оно использует проходы в буферах. Чтобы рассчитать буфер освещения, необходимо получить доступ к этим двум процессам:
- Post Process Input: Как только в Unreal будет установлено значение освещения и последующая обработка изображения, процесс сохранится в этом буфере.
- Diffuse Color: это изображение без использования освещения и постобработки с диффузными цветами.
Чтобы получить доступ к этим процессам, вам нужно использовать узел SceneTexture. Создайте его и, выбрав его, перейдите на панель Details. Чтобы получить доступ к Post Process Input, измените значение Scene Texture Id на PostProcessInput0:
Чтобы получить доступ к Diffuse Color, создайте еще один узел SceneTexture и измените значение его его Scene Texture Id на DiffuseColor:
Буфер освещения должен содержать значения только в градациях серого оттенка. Таким образом получается, что вам не нужна информация о цвете из обоих буферов. Чтобы отключить цвет, подключите выход «Color» обоих узлов SceneTexture к узлу Desaturation. Это полностью обесцветит оба буфера:
Чтобы рассчитать буфер освещения, просто разделите SceneTexture: PostProcessInput0 на SceneTexture: DiffuseColor. В этом вопросе очень важно соблюдать верную последовательность:
Используйте узел Clamp, чтобы обозначить порог при котором значения останутся в диапазоне от 0 до 1:
Так должна выглядеть визуализация буфера освещения:
Как вы можете видеть, освещенные области изображения сейчас ближе к белому оттенку, а неосвещенные области ближе к черному.
Дальше вам нужно будет использовать буфер освещения для создания порога.
Создание числового порога
Сейчас в затенении типа cel любой пиксель со значением больше 0.5 будет использовать обычный диффузный цвет. При этом пиксели со значением менее 0,5 будут использовать диффузный цвет с половиной установленной яркости.
Для начала создайте узел под названием If, чтобы иметь возможность сравнить два значения. Благодаря этому вы сможете указывать различные значения в зависимости от результата сравнения:
Теперь подключите узел Clamp к входу A и создайте узел Constant со значением 0,5, подключив его к входу B:
Примечание: В любой момент можно изменить значение входа B, чтобы регулировать порог.
Чтобы получить цветовой диапазон, нужно создайте новую текстуру SceneTexture и установить для Scene Texture Id значение Diffuse Color. Умножьте Color на 0.5, чтобы получить диффузность на половину яркости:
В конечном итоге у вас должна получиться схема:
Резюмируя:
- Узел Desaturation преобразовывает Post Process и Diffuse Color в оттенки серого.
- Узел Divide разделяет Post Process на Diffuse Color, получаем буффер освещения.
- Узел Clamp удерживает значения в диапазоне от 0 до 1
- Узел If выдает нормальный диффузный цвет, если значение освещения больше 0,5. Если это значение меньше 0,5, выводится рассеянный цвет с половиной яркости.
Использование материалов постобработки
Чтобы использовать материалы постобработки, необходимо создать новый объект Post Process Volume, который как правило используются для контроля эффектов постобработки, таких как баланс белого цвета, насыщенность и контраст.
Чтобы предыдущие изменения вступили в силу нажмите Apply и вернитесь в главный редактор. Чтобы создать Post Process Volume перейдите к панели Modes, выберите категорию Volumes и перетащите Post Process Volume в окно Viewport:
Теперь вам нужно указать значение Post Process Volume для последующего использования шейдера типа cel. Выбрав Post Process Volume, перейдите на панель Details и выполнив Rendering Features ⇒ Post Process Materials и щелкните значок +, чтобы добавить новую запись:
В раскрывающемся меню вам нужно выбрать пункт Asset Reference:
Таким образом вам теперь доступен выбор материала. Нажмите кнопку None и выберите PP_CelShader:
По умолчанию изменения в настройках Post Process Volume вступят в силу только после определённых действий. Вам нужно найти параметр Post Process Volume Settings и поставить галочку напротив Extent (Unbound):
Теперь, когда вы применили шейдер cel ко всему изображению, ваша сцена должна выглядеть следующим образом:
Однако это изображение еще далеко от идеального по причине того, что движок применяет эффект сел шейдинга только после тонального отображения (tonemapping).
Применение сел шейдинга перед эффектом Tonemapping
Перед отображением изображения Unreal выполняет процесс, называемый тональным отображением (tonemapping). Оно используется для того, чтобы картинка смотрелась более естественным образом. В начале процесса используется входной цвет и при помощи кривой графика его значение перемещается в новое положение.
Посмотрите, ниже приведены два изображения буфера Post Process Input. Одно из них отображает эффект до tonemapping, а другое после:
Как видите, блики перед применения tonemapping слишком яркие, а после отображения тона они становятся мягче.
Откройте PP_CelShader и убедитесь, что у вас не выбран никакой другой объект для работы. Перейдите к панели Details и найдя раздел Post Process Material, установите Blendable Location в Before Tonemapping:
Нажмите Apply и затем вернитесь в главный редактор. Посмотрите, цвета теперь выглядят намного лучше:
Изоляция сел шейдинга
Чтобы изолировать эффекты постобработки, вам нужно использовать функцию под названием Custom Depth. Этот буфер вы можете использовать в материалах после любой обработки.
Прежде чем вы узнаете, что такое Custom Depth, вы должны знать, что представляет собой инструмент Scene Depth, который хранит информацию о расстоянии каждого пикселя от вида камеры. Посмотрите, как наглядно смотрится Scene Depth:
В Custom Depth хранится та же информация, но только для определенны, указанных вами сеток. Посмотрите, как смотрится изображение викинга с Custom Depth:
С помощью этих двух инструментов вы можете изолировать нужные вам эффекты. Если Scene Depth меньше Custom Depth, можно использовать обычное изображение, однако, когда происходит наоборот, необходимо использовать затененное изображение.
Использование инструмента Custom Depth
Находясь в World Outliner выберите SK Viking и перейдите к панели Details – тут вам нужно найти раздел Rendering и включить Render Custom Depth Pass:
Далее необходимо выполнить процедуру сравнения глубины, открыв PP_CelShader и создав следующую настройку:
Примечание: Узлы Mask (R) являются компонентными масками, которые позволяет вам преобразовывать многоканальные данные в скаляры.
Далее подключите выход cel к выходу A> B, а выход узла If, который вы только что создали, к Emissive Color:
Теперь будут затенены только сетки, которые отображаются в Custom Depth.
Чтобы сохранить изменения нажмите Apply и вернитесь в главный редактор. Посмотрите, как сейчас выглядит ваше изображение:
Этот эффект интересно смотрится, но одновременно с этим изображение получается немного простоватым. Чтобы создать более мягкий переход между цветовыми группами необходимо использовать так называемые таблицы поиска (LUT).
Что такое таблица поиска?
Каждому взрослому человеку известно, что такое таблица умножения и для чего она используется. Согласитесь, гораздо удобнее использовать готовые данные вместо того, чтобы каждый раз производить вычисления.
Таблица поиска LUT представляет собой набор значений (обычно предварительно вычисляемых), к которым вы можете получить доступ с помощью входных данных. Например, в случае с таблицей умножения такими входными данными являются множитель и число на которое происходит умножение.
В контексте этого cel-шейдера LUT — это текстура с некоторым градиентом. Вот четыре примера того, как может выглядеть LUT:
В данный момент вы рассчитываете цвет тени путем умножения диффузного цвета на 0,5. В дальнейшем вместо умножения на постоянную 0,5 вы будете использовать значение из LUT. Делая это, вы можете контролировать количество полос и их переходов, а также получать представление о том, как будет выглядеть затенение при использовании LUT.
Изменение настроек LUT
Перейдите в папку Textures и откройте T_Lut_01. Посмотрите, как выглядит LUT:
В первую очередь вам необходимо изменить значение sRGB. При рендеринге Unreal преобразует любые текстуры с включенным sRGB в линейный цвет, упрощая выполнение расчетов рендеринга.
Параметр sRGB хорош для текстур, которые используются для отображения внешнего вида объектов. Однако многие текстуры содержат значения, предназначенные для математических вычислений. Таким образом, Unreal должен предполагать, что их значения уже верны и при отключении sRGB выполнять их преобразование в линейный цвет.
Для этого вам нужно перейти в раздел Texture и снять флажок с параметра sRGB:
Теперь вам нужно отменить отображение картинки в виде мозаики. Для данного изображения нет нужды разбивать его текстуру на плитки, кроме того этот эффект может создать проблемы в дальнейшем при выборке с краев.
Чтобы отключить мозаику, измените значение Tiling Method оси X на Clamp. Сделайте то же самое для Tiling Method по оси Y:
Использование LUT
Закройте T_Lut_01, откройте PP_CelShader и удалите выделенные на изображении ниже узлы:
Затем создайте Texture Sample и измените значение Texture на T_Lut_01, чтобы создать три полосы с мягким переходом цвета:
Как говорилось ранее, LUT использует входные данные, чтобы определить, какое значение вывести в дальнейшем. В этом случае вам необходимо использовать в качестве входа буфер освещения. Для этого подключите Clamp к UVs узла Texture Sample:
Эта схема сработает по причине того, что буфер освещения и координаты текстуры находятся в диапазоне от 0 до 1. Например, если пиксель из буфера освещения равен 0,5, LUT выведет значение пикселя из середины текстуры.
Теперь вам нужно умножить значение диффузного цвета на LUT. Для этого повторите все соединения, как показано на изображении ниже:
Посмотрите, сейчас причиной действия узла Append является преобразование Texture Sample’s в четырехканальный вектор. Это необходимо, потому что вы не можете умножить трехканальный вектор на четырехканальный вектор (SceneTexture).
Далее подключите все узлы следующим образом:
Теперь вместо того, чтобы умножать значение диффузного цвета на константу вы просто умножаете это же значение на LUT. Таким образом происходит контроль количества полос и их переходов (в зависимости от LUT). Кроме того, буфер освещения определяет, какое значение будет выводить LUT.
Нажмите Apply, чтобы сохранить изменения и закройте PP_CelShader. Затенение теперь будет иметь три полосы с более мягким переходом между собой:
Посмотрите на эти два изображения – это наглядное сравнение того, как могут выглядеть альтернативные LUT:
Что делать дальше?
Вы можете скачать готовый проект.
Как видите, инструменты пост-обработки имеют довольно широкое применение и позволяют создавать множество реалистичных и стилизованных эффектов.
Если вы хотите узнать больше о пост-обработке, изучите раздел документации Post Process Effects.