ИгрыХабрахабр

[Перевод] Делаем стильный водопад из RiME прямо в Unity или UE4

Есть игры с таким запоминающимся визуалом, что страшно считать потраченное на его разработку время, взять хотя бы последний God of War или RDR2. А бывают проекты, которые подкупают своей атмосферной, даже если они далеки от ААА. Как пример — RiME не раз хвалили за стиль, звук и историю. А недавно левел-дизайнер игры перешел в команду CD Projekt Red, чтобы работать над Cyberpunk 2077. Еще RiME вдохновила 3D-художника Math Roodhuizen на создание собственного арта.

Если в прошлый раз речь шла про реку, то в этот раз про стилизованный водопад. И на фоне всего этого я наткнулся на ArtStation на гайд по созданию реалистичной воды. Для удобства все шаги сопровождаются гифками и/или картинками. В первой части разберем, как создавать «волновой эффект», да еще и прямо в игровом движке.

Сначала скажу спасибо Саймону Трюмплеру — художнику из Tequila Games, который работал над RiME. Я был еще новичком в шейдерах и VFX, когда нашел его материал и подумал: «Ого, может я смогу сделать так же?». Рекомендую ознакомиться с докладом, чтобы узнать больше о способах создания стилизованных эффектов (таких как огонь, например).

Особенно это будет полезно людям, которые еще не знакомы с системой Shader Graph. А теперь поговорим про создание водопада. Наша цель: научиться новым способам работы и лучше разобраться в шейдерах.

Для удобства каждый шаг визуализирован гифкой или картинкой. Я буду показывать на примере Unity, но большинство методов применимы и в UE4 — если вы привыкли там работать, то просто повторяйте следом за мной.

Итак, вам понадобятся:

  • Unity 2018.
  • Amplify Shader Editor (плагин Unity). Но если не хотите тратить на него деньги — установите Unity 2017 и скачайте бесплатный Shaderforge из магазина ассетов (новая версия движка не поддерживает этот плагин, но он все еще работает в Unity 2017). Оба инструмента практически одинаковы, разве что некоторые моменты называются по-разному.
  • Autodesk Maya.
  • Что-нибудь для создания или редактирования текстур. Я использую Photoshop, а иногда даже Substance Designer (но для этого водопада он вам точно не понадобится).

Сначала про «волновой эффект», который возникает, когда водопад падает на поверхность. Еще его можно использовать для других целей, например, для создания пульсаций вокруг предметов в воде.

На момент написания статьи Unity имеет свой собственный Shader Graph, который еще разрабатывается. Откройте Unity и убедитесь, что у вас установлен плагин для шейдеров. И пока он не готов, всё же рекомендую использовать Amplify Shader Editor для Unity 2018 или Shaderforge в Unity 2017.

Затем кликните правой кнопкой мыши на материал в Project Tab и перейдите к Create > Amplify Shader > Surface Shader. Создайте новый материал и дайте ему имя (у меня это MAT_WaterWrinkles). При этом новый шейдер автоматически применится.

Помните, что шейдер должен быть назван как в списке папок, так и в самом шейдере после его открытия. Шейдер можно выбрать в любое время во вкладке Материалы > раскрывающийся список шейдеров (для Shaderforge будет что-то вроде PBL шейдера).

Как только вы откроете новый шейдер, то увидите нечто такое:

Не буду писать подробное руководство по использованию Shader Graph, а если вы совсем новичок, то сначала почитайте вводные гайды.

Вот он с тестовой текстурой на плоскости: В любом случае, чтобы получить желаемый эффект, сначала нам понадобится обычный Panner.

Убедитесь, что Wrap Mode текстуры установлен на Repeat. Panner перемещает UV-координаты. В Shaderforge, возможно, придется подключить временный нод к инпуту Panner, у Amplify некоторые из этих базовых значений уже включены в самом ноде.

Но мы хотим добиться вот такого эффекта: Итак, у нас есть движущаяся текстура.

А для этого нужно, чтобы она прокручивалась вот так:

Чтобы получить нужное направление панорамирования, мы должны создать пользовательскую сетку с UV. Как видите, структура нода та же самая — Panner просто перемещает UV-координаты в направлениях U и V (или X и Y). Гифка для наглядности:

Применяя один и тот же материал к другой сетке, мы можем контролировать направление текстуры в 3D-пространстве, когда она двигается в UV-пространстве.

И разместим UV так, чтобы не было видно шва. Для усиления эффекта, добавим еще несколько полигонов и исказим UV, чтобы текстура в центре двигалась быстрее, чем по краям.

Из этого следует важный вывод: хорошие эффекты редко состоят из одной системы и часто представляют собой комбинацию нескольких.

UV-развертка размещена так, что перемещение справа налево в UV-пространстве с Panner превращается в движение внутрь и наружу в 3D-пространстве. Мы получили текстуру, двигающуюся в нужном направлении с правильной скоростью. В итоге мы добились желаемого эффекта. Чтобы не было швов в текстуре на 3D-модели, UV-развертку надо приснепить (хоткей X для снэпа к сетке) к вершинам текстурного пространства по вертикали.

Начнем с базовых вещей. Теперь прозрачность. То есть 0,5 — это оттенок серого, а 0,2 — оттенок темно-серого. Многие простые вычисления, которые вы делаете в шейдере, будут иметь значения от 0 (черный) до 1 (белый). Имейте в виду, что сначала нужно включить эту функцию. При применении этих значений (в данном случае к каналу Opacity главного выходного нода), вы будете управлять уровнем прозрачности материала. В таком случае мы будем использовать тип рендеринга Transparent Cutout — пиксель, отображаемый этим материалом, либо полностью прозрачен, либо полностью непрозрачен. В Amplify можно изменить тип рендеринга (в режиме наложения) с непрозрачного на, например, прозрачный. Это видно на гифке выше — там нет «полупрозрачных» пикселей, отображаемых этим шейдером.

Здесь она подключается к выходу альбедо (цветному) основного нода. Берем градиентную текстуру с шагом и помещаем ее в шейдер.

А тут она подключается к выходу Opacity Mask (этот параметр включается при типе рендеринга Transparent Cutout).

Всё от 1 (белый) до 0,5 (серый) становится непрозрачным, а всё от 0,5 (серый) до 1 (черный) — полностью прозрачным (или вообще не отображается). Видно, что градиентная текстура использует черные и белые значения пикселей, чтобы определить прозрачность или непрозрачность. Opacity Mask создает жесткий отрезок и округляет значения до 0 или 1 в зависимости от того, какое число ближе.

Еще одна текстура в оттенках серого:

Подключена к Opacity Mask:

И догадываетесь, как ее можно использовать: Идею вы поняли.

И то, что я использую только R (красный) выход этого нода. Вы видите в основном синее изображение, прокручивающееся в Shader Graph. Подобные изображения можно упаковать с помощью Photoshop или Substance Designer. Ради оптимизации я упаковал две grayscale-текстуры (текстуры в оттенках серого) в один файл, но это необязательно.

Почему бы не наложить друг на друга две grayscale-текстуры, чтобы сделать эффект ряби более рандомным? Эффект пульсации — хорошее начало, но можно лучше.

Прокручиваю их с разной скоростью и немного в разных направлениях. Я использую одну и ту же текстуру, но добавляю разные каналы. Текстура имеет хороший градиент значений серого, что дает ощущение случайного волнового эффекта.

На следующей гифке есть еще одна вещь, которую мы пока не обсудили — поэтому ваш вариант может выглядеть несколько иначе:

Добавление этих двух волновых grayscale текстур поверх друг друга с разной скоростью и дает близкий к желаемому эффект. Видно, как, например, пиксель со значением 0,2 (который не рендерится) проходит поверх пикселя со значением 0,4 (который тоже не рендерится) и внезапно становится пикселем со значением 0,6 — поскольку мы используем дополнительный нод (0,2 добавляется к 0,4 и получается 0,6).

Вот, чтобы продемонстрировать результат, я добавил grayscale-текстуры друг на друга в Photoshop.

А нам нужно получить это: Тем не менее, шов в конце сетки все еще остается отчетливым.

Вместо этого:

Самый простой способ это сделать — использовать vertex color (цвета вершин). На первой из двух гифок пульсации медленно стихают и становятся меньше, когда они приближаются к краю сетки.

Цвет вершинам можно задать и в 3D-редакторе.
Большинство внешних вершин — черные (то есть имеют значение 0). Каждая вершина модели содержит свои данные (например, координаты X, Y и Z), а также цвет, который имеет значение от 0 до 1. Обратите внимание, вам понадобятся дополнительные Subdivisions, чтобы получить вершины, которые можно раскрасить. Они становятся белыми (ближе к 1) при приближении к центру.

Например, в Maya для раскрашивания можно перейти в меню Mesh Display > Paint Vertex Color и нажать на поле More Options.

Теперь мы можем соединить Vertex Color в нашем шейдере с помощью Multiply.

Я наложил градиент поверх используемых текстур и установил режим слоя на Multiply.

Это приводит к тому, что линии пульсаций сжимаются ближе к краю (цвета вершин в основном выступают в качестве градиента). Градиент усиливает значение серого до 0 (черный), поэтому отрендерить пиксели будет сложнее (они же не отображаются ниже значения 0,5).

Вот полный граф: Я добавил еще несколько нодов, чтобы контролировать толщину линий пульсаций.

Просто поэкспериментируйте со скоростью/направлением прокручивания, настройте текстуру и попробуйте изменить тайлинг, чтобы выжать из эффекта максимум.

О нем поговорим в следующей части. Это поможет нам при создании более сложного шейдера — водопада.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть