Разбор ассета, Face Weighted Normal + RGB mask Pipeline

Всем привет, меня зовут Александр Силантьев, я 3D художник самоучка, работаю архитектурным визуализатором.

От архитектуры решил так сказать отдохнуть и попробовать себя в геймдеве.

3D пайплайн в архитектуре отличается от игрового, поэтому пришлось разучивать новый софт и технологии.

Собственно весь этот процесс я решил совместить с созданием фан арта по сталкеру, о чем писал в прошлых постах.

4_Intro.jpg

Back to Cordon

aleksandr-silantev-artstation-1.jpg

https://www.artstation.com/artwork/L3dNal

Оригинальный ассет



Сам процесс состоит из нескольких этапов:
- Поиск референсов
- Моделирование Lowpoly\Highpoly
- Выравнивание нормалей
- UV Развёртка
- Запекание текстурных карт
- Текстурирование, в моё случае это рисование масок
- Импортирование и настройка ассета в движке

P.S. Все процессы связанные с моделированием и UV происходят в Blender3D



Поиск референсов

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

5_Reference.jpg

Бесплатную программа PureRef давно стала стандартом индустрии для работы с рефами



Моделирование Highpoly

В первую очередь я сделал highpoly модель, но сейчас, на основе полученного опыта, следующий ассет я хочу сделать наоборот, сначала lowpoly. Не все элементы highpoly оказались нужны для итогового запекания.

В целом, вагон это относительно простой ассет для моделирования, много простых форм и повторяющихся элементов. Для большинства объектов я использовал обычный Subdivison моделлинг. Связка Bevel и Subdivision модификаторов позволяет не перегружая исходную сетку лишними полигонами получать сглаженные формы, а геометрию без модификаторов легко адаптировать под lowpoly.

7_Highpoly.jpg

9_Highpoly.jpg

11_Highpoly.jpg

10_Highpoly.jpg

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




12_Highpoly.jpg

Дополнительно были сделаны Highpoly для плашек декалей.


Моделирование Lowpoly


Face Weighted Normals пайплайн подразумевает то что у объекта нет уникальной карты нормалей, чтобы шейдинг на модели смотрелся правильно нужны отбивать грани фасками и выравнивать вертекс нормали, это увеличивает полигонаж, поэтому иногда такие модели называют не Lowpoly, а Midpoly
Итоговый полигонаж получился в районе 50к треугольников.

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

13_Lowpoly.jpg

Фантастические нормали и где они обитают



14_Lowpoly.jpg

15_Lowpoly.jpg

16_Lowpoly.jpg

17_Lowpoly.jpg

Моделируем, углы отбиваем фасками, где-то халтурим



Выравнивание нормалей


После того как моделинг завершен можно переходить к выравниванию нормалей

В Blender выравнивать нормали можно как в ручную так и с помощью модификатора Weighted Normals, он автоматически выравнивает нормали,

но не всегда работает так как нужно, так-же есть плагин Y.A.V.N.E. но последний раз он обновлялся два года назад, я не пробовал с ним работать.

18_Normals.jpg

Меню для работы с нормалями вызывается с помощью Alt+N в режиме редактирования.


Начинаем процесс выравнивания, для надёжности можно скопировать любой полигон на модели который смотрит в нужную сторону и использовать его как образец для остальных нормалей.

20_Normals.jpg

Иногда копируемый полигон может иметь искаженные нормали, выравниваем их с помощью команды Average – Face Area

Выделяем нормали которые мы хотим выровнять и в последним выделяем наш полигон образец, используем команду Set From Faces и нормали с образца переносятся на выделенные полигоны

21_Normals.jpg

22_Normals.jpg



Важно знать


Перед тем как выравнивать нормали, проверьте правильно ли они вывернуты на модели с помощью отображения Face Orientation

23_Normals.jpg

На заметку, нормали слетают при операциях отзеркаливания в режиме редактирования ;)

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



UV Развёртка

После завершения моделирования и выравнивания нормалей переходим к UV развёртке и подготовке модели к запеканию.
Для этого я создаю отдельную сцену в которой остаются только уникальные элементы вагона
Некоторые объекты располагаются на удалении чтобы легче было контролировать запекание Ambient Occlusion

24_UV.jpg

Правильный нейминг объектов позволяет избежать большинства проблем которые возникают на этапе запекания.
Разворачиваем отдельно каждую деталь, я использую обычную команду U-Unwrap.



25_UV.jpg

Различные неровности и растяжки на развёртке я исправляю с помощью бесплатного аддона Tex Tools, в целом у него большой арсенал инструментов, очень рекомендую.


26_UV.jpg

После того как UV шеллы выравнены я использую аддон Texel Density чтобы задать всем шеллам одинаковый тексель, этот функционал есть и у Tex Tool но мне показалось что Texel Density работает быстрее

Нужно отметить что тексель варьируется в зависимости от видимости деталей, например нижняя часть вагона имеет более низкий тексель так как находится постоянно в тени и вне поля зрения условного игрока.


27_UV.jpg

Переходим к упаковке всех шеллов в один атлас, для этого я использую аддон UVPackmaster 2, аддон платный но однозначно стоит своих денег.
Несколько элементов я запаковал вручную так как мне было важна ориентация шеллов, а всё остальное оставил на совесть аддона использовав функцию Pack To Others


Запекание (слышал что у некоторых горит когда пишут Запечка:)

Тут нужно сделать ремарку, в таком пайплайне можно вообще обойтись без highpoly, просто запечь lowpoly саму на себя, этого хватит для работы генераторов, но чтобы не вырисовывать вручную всякую ржавчину вокруг болтиков я всё-же использую highpoly модель для запекания детализации на AO и Curvature картах.

28_Baking.jpg

29_Baking.jpg

На этом этапе всё прошло хорошо, не было каких-либо ошибок которые нужно было исправлять или перепекать в Marmoset Toolbag
Печем стандартный набор для работы в Substance Painter, если что.



Работа с масками


В первую очередь нам нужно создать три пользовательских канала которые будут отвечать за RGB каналы
Для этого заходим в Texture Set Settings жмём на + и добавляем User каналы, для удобства обзываем их R, G, B.

30_RGB.jpg

31_RGB.jpg


Создаём пустышку Fill Layer в ней оставляем только наши rgb каналы и ставим им нулевые значения, этот слой всегда должен быть в самом низу, он будет давать черный фон нашим маскам.
Ну а дальше мы просто создаём слои в которых будем рисовать наши маски
Создаём Fill Layer, оставляем у него Base Color, он ни на что не будет влиять, нужен только для визуальной идентификации каналов, для удобства цвета назначаются соответственно каналам
R – красный G- зелёный B – синий
Значение для пользовательского канала ставим на 1 или любое число больше 0, этим ползунком можно дополнительно регулировать силу маски


32_RGB.jpg

33_RGB.jpg


Там где белый цвет будет проявляться наш материал ржавчины, там где черный будут все нижние слои
Собственно это основа, дальше мы просто рисуем\генерируем наши маски

Например зелёный канал у меня отвечает за ржавчину

Создаём ему Black Mask и начинаем заниматься творчеством

Fill Layer’ов можно создавать сколько угодно, смешивать их различными способами, в целом работать как с обычными материалами.
Единственное что нужно держать в голове, в пределах одной текстуры у вас есть 3 канала и соответственно вы можете смешать только 3 материала.

Можно создать ещё 4й канал который запакуется в альфу (RGBA) но так не рекомендуют делать из-за особенностей сжатия текстур в UE4. Тут нужно ещё почитать документацию, так как есть разные варианты для решения этого вопроса


34_RGB.jpg


На масках не обязательно детально вырисовывать все подтёки, грязь и т.д. потому что разрешение самой маски будет низким, детализацию мы поднимем за счет подмешивания к маске других текстур уже внутри UE4



После того как работа над масками закончена нужно их правильно экспортировать
Для этого идём в File\Export Textures\Output Templates нажимаем на + и создаём свой пресет экспорта
Выбираем R+G+B перетаскиваем в слоты наши каналы User0/1/2 используем режим Gray Channel


36_RGB.jpg

Экспортируем в любом удобном формате, работа в Painter закончена.

P.S. Почему просто не нарисовать красно\сине\зелёную текстуру за один проход не вытащить каналы в UE4 ? Тогда статья была бы в два раза короче. Можно сделать и так, но тогда мы не сможем нормально отключать слои в материалах.


Дополнительно в Blender был покрашен Vertex Color

R – Выделяет деревянные части

G – Создаёт градиенты

B – Выделяет тёмный грязный метал, об этом позже

37_Vertex.jpg

38_Vertex.jpg




Настройка шейдера в UE4

39_Material_Layers.jpg

Все уникальные Quixel материалы в этой сцене


За основу я взял видео урок от Ryan Manning

и доклад Epic Games по игре Paragon

В первую очередь включаем в настройках проекта функцию Layered Materials чтобы вся система работала.
Можно так-же просто использовать систему Material Function, но Layers мне кажется более компактной
Собственно нужно будет создать Master Material, слои Material Layers и Layer Blends функции для смешивания слоёв.
Если что в видео это всё есть.


Master Material

40_Material_Layers.jpg

Создаём обычный материал, переводим его в режим Material Attributes подключаем в него ноду Material Attribute Layers, мастер материал готов



41_Material_Layers.jpg

После того как Master Material готов, нужно создать слои, Material Layers


42_Material_Layers.jpg

Каждый слой сам по себе это примитивный PBR шейдер, чем слои проще тем лучше для общей производительности.


Для каждого типа материалов мы создаём свой Material Layer формируя таким образом библиотеку для нашего проекта.
После того как слои созданы нужно либо создать функцию Layer Blend, либо использовать заготовленные.
Layer Blend это инструмент который будет смешивать наши слои

Базовая настройка выглядит так, мы берём нашу RGB текстуру из пеинтера и прогоняем её через Channel Mask Parameter(позволяет далее выбирать нужные каналы) и используем как Alpha параметр


43_Material_Layers.jpg



Немного модифицируем функцию

Использую Grunge текстуру мы смешиваем её с нашей RGB текстурой и добавляем параметры для контролирования переходов между слоями

Grunge текстура за счет сильного тайлинга позволяет замаскировать низкое разрешение RGB текстуры

44_Material_Layers.jpg

Так-же добавляем параметры для контролирования контраста и тайлинга Grunge текстуры

45_Material_Layers.jpg

Grunge текстуру берём любую на выбор из коллекции Megascans или любую другую какую сочтёте подходящей

46_Material_Layers.jpg

47_Material_Layers.jpg

RGB маска 1024х1024 VS RGB маска 1024х1024 смешанная с затайленой Grunge текстурой 512x512


После того как Layer Blend готов создаём инстанс копию нашего Master Material и в нём начинаем собирать наши слои в разделе Layer Parameters


В слое Background у меня лежит материал в котором смешаны дерево и краска, все остальные слои ложатся поверх него.
В настройках слоя у нас отображается параметры которые мы присваивали слою при создании шейдера
Так-же у нас есть выбор RGB маски
Настройки для регулирования силы влияния маски которые мы создавали в Blend Layer
И последнее выбор канала из которого будет браться маска


49_Material_Layers.jpg

Что нужно учитывать
Используя эту систему в пределах одной RGB текстуры можно смешать один базовый Background материал и только 3 слоя
Если нужно больше слоёв, нужно делать несколько RGB текстур
Сначала я собирался использовать два RGB сета, но проанализировав модель, я понял что смогу обойтись одним.
Один из материалов который используется в вагоне это ржавый, замасленный тёмный метал характерный для нижних частей всех вагонов
Чтобы не тратить на этот слой текстурный канал я использовал синий канал Vertex Color
Залил им всю нижнюю часть и немного сверху чтобы добавить градиентов на крышу

50_Material_Layers.jpg

В качестве Layer Blend использовал готовую функцию LayerBlend_Vertex_Color


51_Material_Layers.jpg

52_Material_Layers.jpg


Так-же можно использовать одни и те же каналы для разных материалов, например красный канал моей RGB текстуры определяет где краска будет отслаиваться от дерева
Помимо этого я решил что сделаю с помощью него потёртости и повреждения на металле
Для этого я создал отдельный Blend Layer в котором из маски вычитается красный канал Vertex Color чтобы повреждения на металле не выявлялись на дереве
Таким образом потёртости металла не образуются на слое с деревом

54_Material_Layers.jpg

1 - Красный канал RGB текстуры


55_Material_Layers.jpg

2 - Вычитаем с помощью Vertex Color деревянные стенки



56_Material_Layers.jpg

3 - Результат на лицо



Проблема с которой я столкнулся


Структура материалов моего ассета подразумевает что у меня есть слои с деревом, металлом и на обоих слоях сверху лежит слой с материалом краски
Проблема – на дереве должна быть очень сильно выраженная карта нормалей, если её применять только на слой с материалом дерева то краска сверху не будет иметь нормалей, если применить карту нормалей так-же к краске то она проявится и на металле, делать разные материала краски для дерева и металла я не хотел чтобы не раздувать и так тяжелый шейдер и чтобы контролировать краску в пределах одного слоя.
Решение
Возможно не самый элегантный вариант, но в моём случае он сработал отлично.
Используем красный вертекс канал в качестве маски Blend Angle Corrected Normals и карта нормалей дерева проявляется только там где нам нужно

57_Material_Layers.jpg

58_Material_Layers.jpg

1 - Нормалка дерева лежит только на слое с деревом


59_Material_Layers.jpg

2 - Нормалка дерева назначена на всю и краску и проявляется на металле


60_Material_Layers.jpg

3 - Нормалка дерева изолирована от метала с помощью Vertex Color




Материал краски

61_Material_Layers.jpg

Cам по себе материал простой, кастомизация достигается за счет последовательного смешивания цветов через Lepr ноды, в качестве альфы используются Grunge текстуры




63_Material_Layers.jpg

В зелёном канале Vertex color нарисованы градиенты, они смешиваются с Grunge текстурой


С помощью параметров тайлинга и контраста контролируем наш градиент

Формируем из таких Lerp узлов последовательность в которой смешиваем разные текстуры


65_Material_Layers.jpg

Дерево смешивается через красный канал RGB текстуры смешанный с помощью Height lepr функции



66_Material_Layers.jpg

Более ярким цветом на маске выделены случайные доски чтобы разнообразить проявление дерева




Дополнительные варианты смешивания материалов


Создаём новую Blend функцию в которой в качестве маски будет нода Absolute World Position

68_Material_Layers.jpg


Почти как у того крутана из Naughty Dog в Last Of Us 2 :D




Декали


70_Decals.jpg

Карта нормалей для декалей


71_Decals.jpg

Декали для знаков и надписей


72_Decals.jpg

Материал Normal Decal


73_Decals.jpgПлашки для декалей


Декали ВКЛ\ВЫКЛ


Также вы всегда можете добавить дополнительные декали чтобы разнообразить ассет и скрыть недостатки от тайловых текстур


Набор граффити от SadSmile Collective



Презентация


С самого начала у меня была какая-то тактика и я решил что буду использовать рейтрейсинг, поэтому весь свет в сцене является динамическим
Всего в сцене 3 источника света
В качестве заполняющего света используется HDRI Backdrop с картой с сайта HDRIHaven,
Дополнительный Directional Light без теней для подчеркивания силуэтов
Основной Directional Light рисующий тени





75_Render.jpg

Для фона используется простая диорама, я хотел сделать максимальный акцент на самом ассете


76_Render.jpg

Чтобы вагон не стоял просто на земле я взял железнодорожный путь из моей сцены с мостом.


78_Render.jpg

Я старался не слишком увлекаться пост процессингом чтобы сохранить нейтральный вид для моего ассета.

После этого я просто расставил камеры и сделал скриншоты через встроенный инструмент в 2х разрешении, добавил немного шарпа в фотошопе и всё, работа готова)



Заключение


Спасибо всем (кто дочитал), надеюсь для кого-то эта статья окажется полезной
Если у вас есть какие-то замечания и предложения по этому пайплайну с удовольствием их выслушаю ;)
Спасибо чатику CG Allies за советы и фидбек
Цитирую слова великих хотелось бы добавить - Делайте больше сечений на цилиндрах.

Всем спасибо, всем работки!


79_Final.jpg

Хоба



738 0 850 14
15
2021-06-28
отличная статья. Спасибо!
2021-06-28
NiLArtотличная статья. Спасибо!
Спасибо вам!
2021-06-30
Отличный разбор! В идеале, хотелось бы ещё сравнить производительность в UE процедурного материала с текстурами низкого разрешения и запечённого с HiRes текстурами. Понятно, что когда у нас много объектов с разными настройками похожих материалов, то процедурный подход сильно облегчает жизнь при создании ассетов. Но как это скажется на FPS?
2021-06-30
Y.A.V.N.E три дня назад обновился.
Пасиб. Толковая статья, отличная работа.
2021-06-30
Михаил Наумов (Mic Nau)Отличный разбор! В идеале, хотелось бы ещё сравнить производительность в UE процедурного материала с текстурами низкого разрешения и запечённого с HiRes текстурами. Понятно, что когда у нас много объектов с разными настройками похожих материалов, то процедурный подход сильно облегчает жизнь при создании ассетов. Но как это скажется на FPS?

Спасибо!
В идеале, в финале этот процедурный материал нужно запекать внутри движка.
Об этом можно прочитать доклад Coalition про создание Gears Of War 4, по сути каждый слой это отдельный материал который имеет свои шейдерные инструкции, чем больше слоёв тем больше инструкций и больше Shader complexity, у Coalition выходило до 15-25 слоёв на объект. Используя свои наработки они запекали результат этих всех слоёв в новый материал с минимальным количеством инструкций.
У такого подхода есть как минусы так и плюсы, более подробно можно прочитать в статье
https://cdn.gearsofwar.com/thecoalition/publicatio...

Если сравнивать с классическим текстурингом, то в начале я пробовал сделать один уникальный 4к PBR набор, но не влез по текселю, ассет такого размера уже выходит за ту грань где можно использовать уникальные текстуры и сохранять приемлемый тексель, даже в 8к например крыша не влезает при 1024 пикселей на метр
2021-06-30
Василий ГорожанинY.A.V.N.E три дня назад обновился.
Пасиб. Толковая статья, отличная работа.

Спасибо, надо посмотреть что там)
2021-06-30
Скрин из режима Shader Complexity вагона был бы не лишним к ознакомлению.
2021-07-01
Ник К (Nick_K)Скрин из режима Shader Complexity вагона был бы не лишним к ознакомлению.
Хотел добавить но забыл в итоге)
К комментарию уже не могу приложить картинки но вот ссылки
https://ibb.co/zx3qgCZ
https://ibb.co/HzvFXrv
https://ibb.co/wSKNTvq

Есть места где материал можно оптимизировать, в этом плане ещё многое предстоит изучить
Материал можно лодировать отключая на дистанции лишние слои, пока не знаю можно ли это сделать на уровне шейдера, но как минимум можно создавать инстансы с меньшими количеством слоёв и присваивать их определённым лодам
2021-08-31
Вначале было сказано что с высоты своего опыта ты теперь сделал бы сначала Лоуполи а потом хай. Мне как новичку это не вполне понятно, а как это связано с "не нужными для итогового запекания элементами в Хай-поли"?
2021-09-01
Yury AleshkoВначале было сказано что с высоты своего опыта ты теперь сделал бы сначала Лоуполи а потом хай. Мне как новичку это не вполне понятно, а как это связано с "не нужными для итогового запекания элементами в Хай-поли"?

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

В итоге упёрся в ограничение по текселю, лоуполи пайплайн сменил на мидполи и как таковая хайполи стало не особо нужна, только для облегчения генерации масок в пеинтере.

Это относится в мидполи пайплайну, в "стандартном пайплайне" проще сделать сначала хайполи и потом лоу и запекать
2021-09-24
Доброго времени суток! Интересная статья. Как я понял, использовалось два UV канала. А зачем нужен второй, можно же обойтись одним, или я чего-то недопонимаю? Очень нужна информация, тоже занимаюсь текстурированием вагона, метрошного).
2021-09-25
Akhmad SaifutdinovДоброго времени суток! Интересная статья. Как я понял, использовалось два UV канала. А зачем нужен второй, можно же обойтись одним, или я чего-то недопонимаю? Очень нужна информация, тоже занимаюсь текстурированием вагона, метрошного).

Приветствую, первый канал используется для уникального текстуринга RGB маски на нем много оверлапов, зеркальных элементов всё для экономии места, второй канал под тайлинг, на нем шеллы можно смещать, вращать, выходить за рамки юдимов, в общем располагать шеллы так чтобы сбить паттер повторяющихся тайловых текстур.
В зависимости от ситуации можно и обойтись одним UV каналом
2021-09-25
Sanekum
Приветствую, первый канал используется для уникального текстуринга RGB маски на нем много оверлапов, зеркальных элементов всё для экономии места, второй канал под тайлинг, на нем шеллы можно смещать, вращать, выходить за рамки юдимов, в общем располагать шеллы так чтобы сбить паттер повторяющихся тайловых текстур.
В зависимости от ситуации можно и обойтись одним UV каналом

Спасибо большое, в итоге сам поразмышляв догнал до этого).
2022-05-22
Sanekum
С высоты опыта эт канеш сильно сказано, учиться и учиться ещё)
Я имел в виду что потратил время на моделинг и скульпт некоторых деталей, например на тележке всякого рода зачески, прослойки между тележкой и буксой, которые в запекании потом вообще не участвовали. Всё изза-того что сначала я хотел делать уникальную нормал карту для всего, скульптил уникальные сварные швы которые в итого заменил декалью со сваркой, и тд.

В итоге упёрся в ограничение по текселю, лоуполи пайплайн сменил на мидполи и как таковая хайполи стало не особо нужна, только для облегчения генерации масок в пеинтере.

Это относится в мидполи пайплайну, в "стандартном пайплайне" проще сделать сначала хайполи и потом лоу и запекать

Позволю себе наглость попросить совета по пружине на тележке: как ты смог её из хай-поли завитушки перевести в красивый лоу-поли цилиндр? (ну или наоборот :D)
P.S. спасибо большое за информативный ответ на предыущий вопрос!)
2024-01-29
Спасибо за отличную статью, особенно для начинающих! То что искал
RENDER.RU