Шейдеры для персонажей в UE4
В этой статье Дзун Фун Дин в подробностях разбирает свой проект «Экспария».
Оригинальный материал можно почитать тут.
Введение
Меня зовут Дзун Фун Дин. В 2010 году я занял первое место в конкурсе моделлинговых демо-рилов на премии CGSA (ее организует Autodesk, чтобы награждать студентов, занимающихся компьютерной графикой). Теперь она называется The Rookies. Я занимаюсь 3D-графикой почти 10 лет. В самом начале я работал игровым художником в Rare UK, а также над серией рекламных материалов для игр к Xbox (Fable III и Halo Reach). Позже я «переехал» в сферу видеоэффектов для кино и оказался в Double Negative London, где работал художником-генералистом и художником по спецэффектам живых существ над фильмами вроде «Джон Картер», «Белоснежка и охотник» и «007: Координаты Скайфолл».
Но все это в прошлом, и теперь я основатель и руководитель собственной студии – вьетнамской Thunder Cloud, создающей высококачественные модели для студий-разработчиков, разбросанных по всему миру и нуждающихся в аутсорсинге. Наша конечная цель – стать студией, делающей анимацию и синематики при помощи графических технологий, работающих в реальном времени. Именно поэтому сейчас я усердно работаю с UE4, попутно используя его для своих исследовательских проектов.
Проект «Экспария»
Вы, вероятно, знаете, что в 2016 году сайт ArtStation запустил официальный конкурс «The Journey».
Меня эта тема очень воодушевила. Я присоединился к конкурсу и планировал создать эпическую 3D-сцену. В целом конкурс длился около 3 месяцев. Я думаю, этого времени достаточно, чтобы художник мог смастерить что-нибудь стоящее, работая над проектом в режиме «фул-тайм». Но, к несчастью, мне пришлось отвлечься на работу в Thunder Cloud, и к сроку я не успел. Либо 3 месяцев и вправду мало, либо мой проект был излишне амбициозным. Но недавно я все же решил его доделать, и поскольку теперь это полностью мой проект, то я снова врубил амбиции на полную катушку.
Моя цель – создать эпический CG-ролик на тему «путешествие». Главным персонажем будет девушка по имени Экспария. Это производное от «explorer», что значит «исследователь» (имена всех моих женских персонажей заканчиваются на «…ария»). Она пилот мехи, чья задача – исследовать для человечества новые миры. Как можно видеть из концепт-артов, у всего этого есть небольшая предыстория: на орбите Земли появилась гигантская червоточина, окруженная странными инопланетными камнями, и это намекает, что это вряд ли природное явление. Червоточина была создана кем-то и явно в дурных целях. Человечество решает отправить флот, чтобы узнать, что находится по ту сторону этой «норы». Все мехи в этом флоте называются «Камикадзе», и не просто так: это авангард, который вряд ли вернется. Пилотов обучили и военному, и научному делу. И нашему главному персонажу – улыбающейся Экспарии – не терпится поскорее отправиться исследовать новые миры, но в то же время боязно из-за опасностей, с которыми она может столкнуться.
Финальным результатом этого проекта будет не просто статическая картинка, а маленькое видео с анимацией и эффектами – и все в UE4. Работая над этим проектом, я хочу прокачать себя и в знании технических деталей, и в создании красивой картинки. Там будут органические персонажи в одежде, роботы/мехи, внутренние помещения с твердым покрытием, фон в виде открытой локации и т.д. В общем, много такого, что поможет мне серьезно продвинуться в навыках, знании рабочего процесса и различных инструментов, используемых вместе с UE4. Кроме того, весь рабочий процесс строится вокруг UE4.
И еще кое-что. Глядя на список челленжей выше, вы, вероятно, задаетесь вопросом: что есть главный элемент этого проекта? Это ее главный персонаж, а также потенциальная способность UE4 рендерить качественную картинку и анимации для последующего использования в производстве. Раньше я занимался преимущественно персонажами, поэтому одна из самых сильных сторон Thunder Cloud – как раз «персонажка». Так что «Экспария» служит для меня и студии своеобразным тренировочно-исследовательским проектом.
2D-концепт
По-настоящему хороший 3D-художник должен и хорошо рисовать, и хорошо обращаться с 3D-инструментами. Я тренировался рисовать цифровое 2D и концепт-арты примерно в то же время, когда начал работать с 3D. Будучи 2D-художником, я могу быть свободнее в плане идеи, замысла и цветов – меня не ограничивают технические возможности ПО для 3D. Что касается именно этого проекта, то здесь я хотел добиться очень стилизованной «визуалки», где цифровая 2D-рисовка сочетается с небольшим «налетом» PBR-шейдеров.
Вот рисунок, который я нарисовал одним из первых и использовал в качестве главного концепта при создании девушки. Кроме того, это главный референс для создания шейдеров и текстур. То есть мне пришлось хорошенько разобраться, на каких принципах строится 2D-рисование, чтобы результат выглядел как нарисованный и был привлекательным для зрителя, и в то же время использовать мои навыки в 3D, чтобы перевести это все на трехмерный «язык». Кроме того, я многому научился у других 2D-художников – тому, как они интерпретируют/решают/«рендерят» определенные области 2D-персонажа.
К примеру, на мой взгляд, глаз на 2D-рисунке выглядит гораздо естественнее и интереснее, чем тот, что генерируется и рендерится на 3D-модели. Поэтому я, во-первых, научился рисовать в 2D и изучил фундаментальную структуру определенного 2D-стиля. Затем я начал воспроизводить эту структуру и стилизованные элементы в 3D (в данном случае – в UE4).
Что касается всего проекта целиком, то возможность самому нарисовать 2D-концепт позволила мне предугадать, как будет выглядеть финальная 3D-сцена. Он задает стандарт визуального качества, который моя 3D-модель должна достичь. Это также помогло мне определить важность/приоритет разных элементов сцены, а также прикинуть, каким будет рабочий процесс и сколько времени потребуется на создание проекта. К примеру, глядя на концепт-арт, понимаешь, что ключевые элементы – это девушка и ее робо-костюм, однако стенкам и полу ангара, который ее окружает, тоже требуется определенный уровень детализации. Кроме того, в кадре есть гигантские космические корабли и открытые пейзажи – это фон, который очень далеко и окутан туманом. Таким образом, это дает мне быстро оценить необходимый уровень детализации и то, как построить рабочий процесс, будь то создание хай-поли объекта и карты нормалей, обычной модели с диффузной картой или даже использование мэт-пейнтинга (для далекого горного ландшафта) и т.д.
Пайплайн
Мы предлагаем услуги по созданию персонажей для клиентов по всему миру и с широкими вариациями по стилю и техническим требованиям к «железу» – от мобильных устройств до самых топовых компьютеров.
У нас есть один главный «материнский» пайплайн для персонажей всех типов. Возможно, это прозвучит глупо, но сначала мы «примеряем» этот универсальный пайплайн к будущему проекту, а затем потихоньку «раздеваем» его, убирая одни (ненужные) части и добавляя другие (нужные). В итоге мы получаем наилучшим образом оптимизированный пайплайн, который подогнан под проект, но не нарушает общую структуру. Благодаря этому команда делает работу очень быстро, не путаясь в разных пайплайнах для разных проектов – ведь все они наследуют от одного «материнского» пайплайна.
Сам «материнский» пайплайн выглядит так:
А вот так выглядит его «раздетая» версия для вручную нарисованного персонажа с текстурами и маленьким количеством полигонов:
А это версия для проекта со стилизованными PBR-персонажами, где требуются лепка, большое количество полигонов и запекание (как в Overwatch):
Инструменты
Что касается ПО, которое я и команда используем в Thunder Cloud, то на разных этапах пайплайна я использую разные инструменты, начиная от распространенных вроде Maya (мой главный инструмент для моделирования), Zbrush (главный для лепки), xNormal (для запекания) и Substance Painter (для PBR-масок) до не очень популярных вроде BodyPaint 3D (для текстурирования), Crazybump (для создания текстурных карт) и нескольких инструментов Thunder Cloud, которые я написал сам, чтобы упростить создание персонажей. К примеру, инструмент для волос GMH2 – это как раз мое творение, и я использую его в «Экспарии», чтобы конвертировать 3D-сетки волос в текстуры волос. Более подробно о GMH2 можно почитать тут.
Для этого проекта использовались и другие инструменты, написанные мной:
Это менеджер запекания, который ускоряет процесс запекания из хай-поли в лоу-поли. Он может делать выборочное запекание, автоматически отделять сетку для запекания ID-карты, автоматически генерировать «кейдж» (от англ. «cage»; и это сетка, используемая для запекания карты нормалей) и т.д. Кроме того, я ищу способ настроить коммуникацию между ним и xNormal – для пакетного запекания.
Это экспорт-менеджер – маленький скрипт, помогающий экспортировать персонажа вместе с названием материала. Он позволяет мне быстро и просто переключаться между UE4 и Maya.
Выбор стиля и производство
В этом проекте я старался добиться очень «гладкого» PBR-стиля, который можно наблюдать в Overwatch, Blade & Soul и т.д., а также в цифровых 2D-работах от художников вроде Mujiha, BdsPlace и т.п. Поэтому я не сильно углублялся в детальную лепку, а старался делать все как можно глаже и «чище» – больше всего внимания я уделил большим и средним участкам вроде больших выпуклостей и краев, больших одежных складок и общей форме частей тела вроде носа, глаз, губ и т.д.
Маленькие детали будут почти не видны после обильной «закраски» на стадии текстурирования. Кроме того, эти детали сложно модифицировать и они часто «теряются» из-за работы над другими элементами. Поэтому при лепке высокополигональной модели я делаю лишь большие и средние части – те, что будут видны после наложения запеченных карт.
Что касается лоу-поли модели, то я делаю также, как сейчас принято делать для топовых игр к некст-ген консолям. Я отвожу под самого персонажа где-то 50 тысяч треугольников, и еще 40-60 тысяч – под волосы. В общем, для лоу-поли модели вполне достаточно. Я моделирую каждый объект как отдельную сетку – чтобы потом было проще запекать. Кроме того, в конечном счете они будут использоваться для синематика, поэтому не должны быть слишком лоу-поли, но при этом – достаточно «легкими» для нормального рендера в UE4.
В моем проекте значительную роль играют вручную нарисованные текстуры – от них зависит то, насколько качественно будет выглядеть модель. Но я эти текстуры с нуля, как правило, не рисую. Я запекаю несколько карт из xNormal, затем комбинирую и фильтрую их в Photoshop – чтобы быстро создать базовую карту, представляющую собой конечный результат (как можно ближе к желаемому).
Таким образом, я постоянно вижу, во что превращается текстура, и могу быстро и просто контролировать конечный результат. Я называю эту базовую текстуру «процедурной картой», потому что она полностью создается в Photoshop при помощи фильтров и простых масок, безо всякого рисования. Когда я доволен видом, цветами и общей формой/объемом на процедурной карте, то открываю BodyPaint, при помощи которого начинаю доводить текстуру до финальной версии. Я работаю в BodyPaint, потому что у нее лучше интерфейс и горячие клавиши, и она больше похожа на Photoshop, чем любая другая программа для текстурирования. Кроме того, я могу легко переключаться между BodyPaint и Photoshop, работая над одним и тем же PSD-файлом.
Что касается стилизации, то мне кажется, что самой важной картой является диффузная – ее нужно сделать хорошо в самую первую очередь. Сделав хорошие диффузные карты для всего, я экспортирую модель в UE4. Там я делаю сцене освещение и HDRI – для выявления дефектов и предпросмотра других карт (неровностей, отражения, нормалей и т.д.).
До сих пор мой рабочий процесс был довольно линейным, но с этого момента (после рисования диффузной карты) я начинаю скакать взад-вперед между моделированием, изменениями в диффузной карте, карте нормалей и прочих картах, а также разработкой шейдеров – пока не получу нужный результат.
Материалы
Честно говоря, UE4 я скачал совсем недавно, поэтому мне еще многому нужно научиться. Я не делаю суперсложных материал-функций и графов, а также не пишу собственные ноды для шейдеров – я не настолько технический спец. На данный момент я ограничиваюсь лишь стандартными нодами и схемами.
Сначала я беру в UE4 базовый материал, который кажется мне самым близким к тому, что мне нужно. Например, материал для кожи. Я начинаю с шейдера Subsurface и потихоньку двигаюсь вперед, глядя на 2D-концепт, чтобы понять, какой элемент я упустил, и ища способ повторить этот эффект в UE4.
Ниже – пошаговый разбор работы над этим материалом:
Базовый материал (шейдер SubSurface) с базовыми параметрами – как отправная точка.
Добавляем базовую текстуру.
Добавляем нод Fresnel и текстуру с затемненной кожей, чтобы с их помощью управлять градиентом, направленным от края силуэта к внутренней части персонажа. Похожим образом делают затемнение 2D-иллюстраторы, а в 3D в качестве примера можно привести Street Fighter.
Кроме того, этот эффект можно регулировать при помощи нодов «falloff» и «width».
Создаем нод с зеленым цветом, создаем нод Multiply, а затем подключаем его к диффузной текстуре и ноду с зеленым цветом. Далее подключаем всю эту конструкцию к слоту Subsurface Color. В итоге у нас должен получиться эффект подповерхностного цвета.
Создаем нод Fresnel, чтобы смешать вместе два подповерхностных цвета и тем самым воссоздать едва заметный градиентный переход как на исходном концепт-арте.
Я также создал отдельную материал-функцию, основанную на нодах Fresnel, чтобы с ее помощью управлять позицией и силой градиента. Кроме того, эта функция позволяет добавить немного шума – чтобы кожа выглядела более естественно. Ниже эта градиентная материал-функция показана более подробно:
Далее добавляем несколько нодов для усиления/ослабления различных эффектов, а также дополнительные текстуры для кровеносных сосудов и пор – чтобы кожа выглядела, опять же, более естественно. Разные комбинации дают разный результат, поэтому эту конструкцию можно применять не только на шейдере для кожи.
Карта неровностей/отражений, а также несколько специально добавленных отражений.
На 2D-концепте в некоторых местах много бликов и маленьких «искр» – почти как от материала для автомобильной краски – поэтому я беру текстуру с мелким шумом, а затем через ноды Blend_Overlay подключаю ее к картам неровностей/отражения и нормалей. В результате, если более пристально всмотреться в эти блики, то на них будет виднеться небольшая детализация.
Впрочем, мне по-прежнему нужно было сделать области с отражениями более выразительными. В итоге я нашел граф, с помощью которого мог управлять местами с отражениями и светлыми участками, при этом не сильно мешая освещению сцены.
Этот граф похитрее прочих, и я создал его при помощи нода Reflection Vector в UE4. Подключаем его к слоту UV на текстурном ноде и в результате получаем что-то вроде сферической текстуры с отражениями.
Впрочем, после нескольких тестов обнаружилось, что для правильной работы этого нода в качестве текстуры нужна кубическая карта. Процесс конвертации 2D-изображения в кубическую карту довольно прост (это делается в Photoshop), но это нужно делать практически вручную. А если учесть, что вам придется много раз сверяться с результатом, постоянно возвращаясь назад, то это занятие может потребовать кучу времени. Поэтому я взял длинную плоскую 2D-текстуру с отражениями из Photoshop, применил ее на неосвещенную сферу, поместил внутрь этой сферы куб, а затем получил на этом кубе рендер от сферы, которая его окружает. Таким образом, я просто чуть правил карту отражений в Photoshop, импортировал ее в UE4 и тут же превращал в кубическую карту. Затем подключил к этой карте отражений нод Blend_Screen, раскрашенную текстуру и нод Fresnel, тем самым получив отличную карту отражений, смешанную с раскрашенной текстурой.
Я также создал специальную материал-функцию, чтобы с ее помощью управлять несколькими параметрами на карте отражений – вроде интенсивности областей с отражениями, базового значения отражения, затухания на ноде Fresnel, карты отражений для наложения масок и т.д.
Вот так шейдер кожи выглядит в итоге. Я не тестировал его за пределами этого проекта, но все равно очень доволен финальным результатом – у меня получилось воссоздать стиль 2D-рисовки и сохранить информацию об освещении, а также осталась возможность добавить дополнительный уровень детализации вроде отражений и подповерхностного цвета. На этом о шейдере кожи, пожалуй, все, и позже я расскажу о шейдере глаз, который получился более мудреным, но базируется на том же принципе.
Цель и ограничения
Моей конечной целью было создать трехмерный кино-ролик, который выглядел бы как цифровой 2D-рисунок. Проект служит прокачке моих навыков в создании картинки, которую я могу получить при помощи UE4. Таким образом, если результат хорош, и хорош независимо от условий (в разном освещении, с разных ракурсов и на разном расстоянии), то я не против и немного сжульничать.
Например, что касается подповерхностного градиента Fresnel Ramp (он описывается в разделе «Материалы» выше) – было бы правильней, меняйся он в зависимости от направления света, как это происходит с настоящим подповерхностным рассеиванием. Но поскольку это очень «хрупкий» элемент, я остановился на простом градиенте, основанном на нодах Fresnel. Вот только для персонажей, на которых падает много света, это может не сработать. Подповерхностный цвет должен меняться в зависимости от направления света, а не ракурса. Но в моем случае этого достаточно.
Каждый раз, добавляя своему шейдеру новый слой детализации, я должен был проверять, правильно ли он смотрится и как ведет себя при изменении освещения/ракурса. Иногда эффект выглядит здорово, если это просто фронтальная статичная картинка, но супер странно, если смотреть на объект сбоку (например, это касается эффекта размытости на картинке ниже). Поэтому мне приходится балансировать между тем, что выглядит хорошо, и тем, что работает хорошо, или даже искать совершенно новый способ, чтобы воссоздать этот эффект с нуля.
Структура
Возможно, мой подход не выглядит аккуратным, однако у меня есть все необходимое для достижения желаемого результата, поэтому я всегда могу вернуться и все поправить. К примеру, в будущем я планирую модифицировать графы для карты отражений и подповерхностного градиента. Эти материал-функции уже систематизированы и сохранены в моей собственной библиотеке – они ждут, пока у меня освободится время, чтобы заняться ими как следует.
Баланс
На мой взгляд, после добавления в шейдеры всех красивостей нужно сделать шаг назад и оценить, далеко ли я ушел от желаемой цели. В этом проекте я старался, чтобы стиль был предельно похож на цифровую 2D-рисовку. Поэтому, если я вдруг замечал, что что-то выбивается из общего ряда или выглядит неестественно, тут сразу же это правил.
К примеру, если при работе над кожей переусердствовать с картой нормалей, модель начнет выглядеть слишком 3D-шной.
Работа над лицом
В своих старых проектах я просто загружал в UE4 вручную нарисованные текстуры, добавлял немного освещения и… все. Результат, разумеется, выглядел неважно. Вручную нарисованные текстуры выглядят хорошо и «излучают» свой неповторимый стиль лишь без освещения. Но стоит добавить света, и начинаются большие проблемы, потому что на модель теперь влияет не только ее главная текстура. В моей сцене есть тени, яркие участки и отражения, и если «врисовать» их в текстуру, они попросту потеряются, а сама базовая текстура будет выглядеть буквально нарисованной на персонаже.
Эта Дива – один из моих старых проектов, когда я еще не сильно углублялся в то, как работает UE4. Поэтому здесь все очень просто. Но работая над «Экспарией», я старался, чтобы освещение/тени/отражения работали на модели как можно корректней. Особенно это касается элементов лица – глаз, носа и рта. Я могу потратить целый день за правкой текстуры, редактированием модели, постоянными изменениями в шейдере, шаг за шагом – просто чтобы все смотрелось как нужно.
Весь мой рабочий процесс довольно прямолинеен, но лишь до тех пор, пока не наступает время «шлифовки». Эта стадия может отнять столько же времени, что и все предыдущие, но оно того стоит. У меня нет простого и понятного решения для того, как выдать нужный результат с самого первого раза. Иногда я даже возвращаюсь назад к модели и меняю старую или приделываю новую часть – чтобы все работало для созданного мною шейдера.
Глаз
Сначала у меня все было объединено в одном фрагменте, но затем я разбил глаз на несколько частей (см. ниже) – чтобы у меня было больше контроля над отдельными элементами вроде отражений, ярких частей, вращения глаза и т.д.
Ниже – граф для шейдера глаз:
Ресницы
Вначале ресницы были нарисованы прямо на текстуре лица, но затем я поместил их в отдельную «листовую» сетку. Более того, для финального результата я даже продублировал сетки для ресниц, чтобы придать этому элементу больше объема. Я старался использовать для шейдера настройку Translucent (выставляется в Details > Material > Blend Mode), потому что ее сглаживающая (AA) альфа-маска гораздо лучше, чем у настройки Masked. Единственный недостаток – приоритет сортировки, но поскольку глаз имеет аккуратную вогнутую форму, на сортировку в этом случае можно не обращать внимания. Еще один вариант – шейдер с прозрачностью, на который наложен эффект дизеринга. Он тоже дает хорошее сглаживание, но не подходит для тонких линий, а также полупрозрачных и двигающихся поверхностей.
Губы
Во время лепки в Zbrush я оставил губы почти без детализации. Мне удобнее добавлять детали позже, в Photoshop, т.к. благодаря этому я могу свободно пробовать разные типы деталей и тут же смотреть, что получилось. То же касается и деталей для кожи (к примеру, пор) – предпочитаю добавлять их на текстуру, а не во время лепки.
В качестве оффтопа – иногда мне нужно анимировать один из элементов и отрендерить его анимацию, чтобы я мог в подробностях рассмотреть, уживаются ли внесенные изменения анимации/деформации с освещением/ракурсом. Это касается, к примеру, губ, открытия/закрытия глаза и т.д. Анимировать/деформировать эти вещи в UE4 довольно просто – я просто подготавливаю серию так называемых «блендшейпов» (от англ. «blend shape»; в Maya это разные варианты одной и той же сетки, обладающие одной топологией, но разными формами). Почему именно «блендшейпы»? Потому что они быстрее тестируются и их деформацией управлять гораздо проще, чем скелетной анимацией. Затем анимируем «блендшейпы» в Maya, экспортируем всю последовательность в UE4 и делаем тестовый рендер.
Рендер
Для этого проекта я использовал самые высокие настройки, потому что в дальнейшем вся эта сцена будет использоваться для маленького синематика, который можно будет отрендерить в ролик при помощи встроенного в UE4 редактора Sequencer или посмотреть как демо, прежде выставив подходящие настройки видео (включая фреймрейт). Я выкрутил в UE4 все настройки на максимум, чтобы меня ничто не ограничивало в создании как можно более качественной картинки. Оптимизацией можно заняться потом. Ниже пара советов, как повысить рендерные настройки в UE4:
Я отключил статичное освещение и карты освещения, чтобы в итоге у меня осталось лишь динамическое освещение, просчитываемое в реальном времени – у меня не было времени ждать, пока система просчитает все параметры, связанные со светом.
Поскольку сейчас я занимаюсь лишь «шлифовкой» и внешним видом всего и вся, то стараюсь делать освещение как можно проще. В качестве базовой сцены я использовал «блюпринт» (от англ. «blueprint»; это начинка сцены, т.е. список правил, по которым она работает) BP_lightStudio из стартового набора, поэтому вначале у меня были лишь один источник направленного света, солнечный свет и один купол в формате HRDI. То есть никаких лишних «прожекторов» (Spot Light), «лампочек» (Point Light) и т.д., чтобы в дальнейшем они не мешали при решении проблем с тенями и отражениями.