![](https://habrastorage.org/getpro/habr/post_images/12f/3d7/c88/12f3d7c88c3f9a4a4991f377ca1b516b.png)
В прошлом мы уже рассказывали о том, какие существуют карты для моделей и как они используются. А также поведали о том, как сделать имитацию плоского изображения из объёмного с помощью целлшейдинга. Теперь настала очередь сделать объём из плоскости..
![image](https://habrastorage.org/webt/kz/x0/ii/kzx0iijogf5texbjrfqhhc8q0rs.jpeg)
Автор, биотехнолог Людмила Хигерович. Зам. руководителя сообщества Фанерострой |
▍ Поговорим о нормальных картах
Примечание: если вы зашли сюда за туториалом и не настроены читать тонны околонаучной информации об истории развития карт нормалей и о том, как именно они отображаются, то добро пожаловать в предпоследний раздел статьи с практическим руководством по запеканию карт нормалей.
В тексте будет много упоминаний программ, сайтов и сервисов, а также игр и разработчиков игр. Не сочтите это за рекламу. Также в тексте будут встречаться рендеры моделей и текстуры из различных игр. Это иллюстративный материал, приведённый в качестве примера работы той или иной карты. Все права на модели и их текстуры из игр принадлежат разработчикам и издателям этих игр. Мои собственные модели подписаны отдельно.
▍ Что нормально, а что нет?
Обычный набор текстур босса из Bloodborne:
![](https://habrastorage.org/getpro/habr/post_images/302/1b3/5c6/3021b35c685050f3adc9238453851379.png)
Всё это — дополнительные элементы модели, так или иначе, улучшающие её внешний вид. По сути своей, текстурные карты — графические файлы («картинки») с соответствующими расширениями (bmp, png, tga, jpg, dds и т.п.), в слоях или строках которых зашифрован не только цвет, но и какая-либо дополнительная информация (наличие и сила альфа-канала, проще говоря, прозрачности; отклонения света, сила блеска, насыщенность и т.п.).
Для того чтобы потом не отвлекаться, проведём краткий экскурс по картам. А чтобы Вы не теряли время, засунем их под спойлер.
СПОЙЛЕР: Карты бывают разные - синие, белые, красныеКарт в 3D-моделировании великое множество, и в каждом графическом движке они имеют свои виды и особенности. Поэтому мы постараемся кратко пояснить, что какая карта делает. Но имейте в виду, что в Вашем конкретном движке карты и соответствующие им кнопки могут незначительно отличаться по названию и функции.
Самая важная карта — карта наложения или UV-map. Она определяет как именно текстура будет ложиться на Вашу модель и какие полигоны будут соответствовать «островам» на текстуре. UV-карта и информация о наложении хранится в файле самой модели (обычно), и изредка в специальных форматах библиотек наложения или программных информационных файлах, а в редких случаях — ещё и в составе алгоритма шейдера (программного сценария графической визуализации).
UV-развертка и модель снаряжения. Сделано мной.
Диффузная карта (diffuse map/ color map) — это карта цвета или раскраска модели. Она пришла на смену объектной заливке и раскрашиванию полигонов моделей напрямую. Долгое время это была единственная карта, применимая к модели (помимо UV), и до сих пор многие игры (особенно мобильные, где максимально важна экономия пространства памяти и вычислительных ресурсов) обходятся только ею. Умелая работа с диффузной картой действительно способна заменить в какой-то степени другие карты, но всё же её часто бывает недостаточно.
Diffuse map сама по себе и на снаряжении. Моё.
Альфа-карта, просто альфа или карта прозрачности (alpha / transparent map) — карта, отвечающая за чтение прозрачности на текстуре. В игровых движках эту функцию на себя часто берёт диффузная карта, в которую встроен альфа-канал (наверняка Вы видели эту кнопку в фотошопе). Он может быть как действительно прозрачным (png файлы), так и просто нести информацию о прозрачности (dds и tga форматы), не отображаясь в файловой системе компьютера, как прозрачный.
В некоторых программах (например, в Keyshot или Daz studio) Вам иногда потребуется альфа-карта как отдельный файл (для сложных текстур, например, волос и ресниц). В таком случае Ваша карта будет выглядеть чёрно-белой, где чёрный цвет означает 100% прозрачность, а белый — 100% непрозрачность. Причём для Даза и Кейшота даже необязательно наличие именно альфа-канала на альфа-карте, главное соблюсти цветовую пропорцию, да, всё сложно. А как Вы хотели?
Альфа-карта прозрачности для волос. Моё.
Карта блеска (specular map) — карта, ответственная за силу и иногда цвет блеска. Как нетрудно догадаться, чёрный цвет означает отсутствие блеска, белый — его максимум (в некоторых движках может потребоваться вмешательство альфа-канала, но в общем случае это не нужно). Кроме оттенков чёрного и белого спекуляры могут нести и другие цвета. Например, Разверстый дракон в игре Dark souls блестит оттенками синего и фиолетового (если Вы его успеете рассмотреть, конечно).
Карта блеска (specular) и её действие в кейшоте (тоже моё).
Цветной спекуляр разверстого дракона из Dark souls 3.
Карта свечения (emission map/ glowing map) — карта, название которой прямо отображает её функции. Как нетрудно догадаться, чёрный цвет означает отсутствие свечения, чисто белый — максимальное свечение. Но большинство игровых движков читают не только силу белого, но и все доступные оттенки цветовых каналов, позволяя раскрасить условного дракона во все цвета радуги. При этом некоторые графические движки позволяют читать карту свечения как источник света — то есть, создавать от него блики на других частях модели и других моделях (например, тот же Кейшот или движок Скетчфаба).
Карты свечения и их действие на примере Стража древних богов из Bloodborne.
Карта пространственного отражения (environmental map/ metallicity map). Этот термин имеет два значения: карта наложения отражения (отвечает за то, какие участки модели будут иметь это свойство) и собственно текстура отражения (также environment map/ cubemap/ metallmap/ sphere map и т.п.). В первом случае существуют разные подходы к её осуществлению, обычно используют очень любимый нами альфа-канал, добавляя его к различным другим текстурам. Например, альфа-канал нормали в Скайриме отвечает за наложение этого самого отражения, если в настройках nif-модели прикрепить соответствующий металлик или отражение. При этом сила блеска отражения берётся с карты — пометка _m (metalicity).
Карты металличности, цвета и нормалей из TES V: Skyrim. На диффузной карте видны артефакты альфа-канала от криворукого разработчика. Вообще, про кривизну рук разрабов Скайрима у меня много хороших слов. Но о грустном как-нибудь в другой раз.
Что-то подобное есть и в Dark souls 3, где в альфа-канале нормали закодированы участки металлического блеска и карты окружения, а в аномально светлом спекуляре — сила и оттенок этого блеска.
Карты для кирасы рыцарского сета из Dark Souls 3 (сверху вниз: диффузная, карта нормалей и спекуляр). Сбоку карта окружения (с фрагментом неба) и её отражение на кирасе. Отметим, что карты окружения в DS3 динамические, и сменяют друг друга по мере продвижения по локации.
Карта подповерхностного рассеяния и просвечивания (translucent map) — немного схожи с предыдущими картами. Эти карты отвечают за то, как модель будет выглядеть «на просвет». Если Вам кажется, что это какая-то бесполезная функция или вообще аналог прозрачности, то вы ошибаетесь. Посмотрите через свою руку на просвет (на лампу или солнце) и Вы увидите, что пальцы и перепонки у их основания словно светятся, просвечивают. То же самое и с полупрозрачными минералами (кварц, яшма, янтарь и т.п.), с частями тела людей и даже листьями.
Карта подсвечивания для женских персонажей и карта просвечивания для крыла драконов в TES V: Skyrim.
Да, в большинстве своём Вы этого не заметите, но рендеры моделек людей с включённым транслюсентом выглядят живее и реалистичнее прочих. Да и, честно сказать, я обалдела, когда впервые увидела такой эффект на крыльях пикирующего дракона в Скайриме, и до сих пор испытываю эстетическое удовольствие, бродя с факелом по кристальным пещерам Элден Ринга (ох уж эти вкусные кристаллы, мммм).
Карта света и карта оттенка (lightmap/ambient occlusion map/ tintmap) — карта, отвечающая за то, как Ваша модель будет реагировать на свет. Некоторые движки читают эти карты подобно картам рассеяния, придавая эффект просвечивания, некоторые просто читают её как маску, добавляя оттенки и световые блики к диффузной карте. Изначально эта карта служила для создания светотени, создавая эффекты затенения и освещённости на модели для экономии ресурсов.
Честно говоря, я не очень помню, откуда эта модель, так как предоставил её друг, для наглядности. Кажется, из Bless online. Слева модель без карт света, справа — с ними, отображаемые тени от лайтмапа делают стилизованную модельку реалистичнее и приятнее глазу.
Сейчас для этого иногда используют более продвинутую версию — карту пространственного освещения (ambient occlusion map), которая, по сути, является гибридом спекуляра и лайтмапа, имитируя свет, тень и блики. Однако, в отличие от лайтмапа, АО не заменяет собой эффект освещения, а читается графическим движком вместе с тенями от источника света, придавая глубину теням для экономии производительности в больших сценах.
В некоторых случаях карта оттенка имеет вид сине-красно-зеленых пятен (как, например, в Witcher 3 или Raid Shadow legends) и сочетает в себе карту оттенков, карту блеска и карту наложения пространственного отражения, закодированные в разных цветах.
Слева: карта Ambient occlusion для сцены боя из игры Raid: Shadow legends, справа вверху: рендер внутриигровым движком (на базе Unity), справа внизу — рендер без окклюзии. Хорошо видно, что карта света и тени из АО создаёт эффект объёма и придаёт живости рендеру. Хочу заметить, что для сцен окружения эта игра использует только диффуз и окклюзию, экономя место и производительность.
Карта смещения (displacement map): чёрно-белая карта, которую графический движок игры или редактора читает, как искажение поверхности модели. В отличие от нормалмапа, дисплейс-карты не имитируют объём, а непосредственно «показывают» движку, как именно должна выглядеть модель, благодаря чему на финальном рендере модель действительно будет иметь объём, а не его иллюзию. Но работая с дисплейс-картами важно учитывать множество нюансов, начиная от того что каждый движок читает их силу и соотношение цветов по-своему, и заканчивая тем, что дисплейс-карты — это векторная информация, и изменение размера модели или положения её в пространстве могут значительно исказить финальный вид.
Слева — тестовый рендер с включёнными displacement и emission картами, справа — рабочий режим без дополнительных карт (только с диффузной). Робот мой.
Карта высоты (bumpmap) — первый предшественник дисплейс-карт и карт нормалей. Чёрно-белая текстура, в которой сила белого определяет силу «выдавливания» объёма на поверхности модели. Сейчас бампмапы как таковые почти не используют (разве что в единичных проектах или в составе шейдера), предпочитая им более продвинутые карты смещения и нормалей, так что сам термин bumpmap сейчас употребляют часто как синонимичный displacement и normalmap, хотя это и не совсем верно.
Нормальная карта (правильнее говорить «карта нормалей», normal map) — карта, имитирующая объём. Она создаёт видимость неровной поверхности за счёт переходов света и тени. Подробнее о тонкостях отображения нормалей мы поговорим позже.
- Что такое нормали?
- В отличие от повседневной жизни, в математике нормаль определяется отнюдь не общественным сознанием.
- Нормаль в 3D-моделировании — это перпендикуляр к поверхности модели (обычно к вершине многоугольника, но на самом деле к любой точке поверхности). Если Вы помните школьный курс геометрии, то должны знать, что есть такое понятие, как касательная (линия или плоскость). Так вот, если провести касательную плоскость к поверхности модели в выбранной точке, а потом в этой же точке опустить перпендикуляр к поверхности касательной, это и будет нормаль.
- Запомните касательные! Они нам ещё пригодятся!
![](https://habrastorage.org/getpro/habr/post_images/7ce/fc9/c43/7cefc9c43657128198c279b715fc184a.png)
![](https://habrastorage.org/getpro/habr/post_images/3ed/6dd/713/3ed6dd713d957313e237f0235dd377bf.png)
В 3D-моделировании вектор нормали проводится к каждой точке поверхности модели (в зависимости от работы движка: к каждой вершине, каждому отдельно взятому полигону или каждой точке меша в пространстве. Последнее сейчас наиболее распространено, но затратно по ресурсам вычислительной техники). Совокупность направлений этих векторов визуализируется как перепады поверхности модели: выступы, впадины и заломы. Если разница между направлениями двух соседних векторов большая, то и перепад будет казаться более резким. Соответственно, чем больше полигонов и вершин, и чем больше разница в векторах нормалей, тем подробнее поверхность модели и тем разнообразнее детализация.
![](https://habrastorage.org/getpro/habr/post_images/12f/3d7/c88/12f3d7c88c3f9a4a4991f377ca1b516b.png)
Нормали к поверхности на основе вершин в высокополигональной модели. Да, это Клавикус Вайл (мое).
Примечание: в современных графических движках есть такая функция как «сглаживание» (smoothing). Она отвечает за то, насколько «грубо» читается переход от одной нормали к другой (от одного полигона к другому или насколько сильно искажён полигон).
![](https://habrastorage.org/getpro/habr/post_images/2c8/e5c/ca6/2c8e5cca61f06b1c98bf57a38c9f3647.png)
Иногда для лучшего сглаживания моделей придется разбивать полигоны на треугольники.
При низком сглаживании модель кажется рубленной или мятой, при высоком замыленной. Единый меш (кусок модели с объединёнными вершинами полигонов), к которому применено сглаживание с заданными настройками, называется группой сглаживания (smoothing group):
![](https://habrastorage.org/getpro/habr/post_images/b0f/92d/1ec/b0f92d1ecc019d8f9663729c37212f9d.png)
Более сглаженная и менее сглаженная геометрия лапки. Моделька моя.
При этом важно понимать, что вычисляется переход между нормалями только соседних вершин в составе меша (единого куска поверхности модели) или группы сглаживания:
![](https://habrastorage.org/getpro/habr/post_images/fa0/aa6/ae8/fa0aa6ae89028b498f26cb2cc79f5edb.png)
Сглаженная и не сглаженная сферы.
Если вершины полигонов в меше («теле» модели) не объединены, то есть, каждый полигон сам по себе, то для каждой вершины каждого отдельного меша нормаль считается отдельно, из-за чего модель также кажется рубленой и грубой.
Однако если сейчас многие киностудии и даже игроделы могут себе позволить сделать модель с парой миллионов полигонов и не сжечь при этом видеокарту (хотя некоторые игры от Square enix всё-таки сожгут), то на заре игропрома такой роскошью не могли похвастаться даже крупные студии. Да и сейчас такое выглядит не слишком-то разумно и экономично. Как выходили из положения тогда?
▍ Намальна? Намальна!
Если нормали к поверхности модели определяют, как на нее ложится свет, то нельзя ли обмануть визуализацию?
Можно. Причём для этого существует великое множество способов — начиная с обмана зрения с помощью карт цвета и заканчивая специальными программными алгоритмами пост-обработки (шейдерами). Но сегодня мы ограничимся картами нормалей.
Точно не известно, кто именно был пионером применения техники создания карт нормалей в играх (хотя точно известно, что распространение эта технология получила благодаря приставке Sega Dreamcast, первой игровой консоли со специальными алгоритмами чтения карт).Карта нормалей или normal map — специфическая текстурная карта, благодаря которой свет в 3D-программе или графическом движке игры понимает, под каким углом ему нужно отражаться от поверхности модели.
Однако известно, что первым подобный алгоритм описал Джеймс Ф. Блин в 1978 году (эксперт по компьютерной графике лаборатории НАСА). Позднее его идею развили Кришнамурти и Левой, представив свою идею на ежегодной выставке-конференции SIGGRAPH в 1996 году. Там они впервые представили практический способ построения карт смещения в NURBS (неравномерный рациональный базисный сплайн, проще говоря — математическая модель, состоящая из совокупности кривых). Но практически применили перенос детализации с высокополигональной модели на низкополигональную болванку только спустя два года, когда почти одновременно вышли статьи Коэна и Сигнони (не уверена, как правильно читается фамилия), описывающие процесс хранения данных о детализации поверхности в текстурной карте и собственно процесс «запекания» и проекции деталей с высокополигональной сетки на низкополигональную. Тогда же и был придуман алгоритм, которым пользуются до сих пор: кодирование отклонения векторов нормали в цвет.
Теперь нормали проводятся не к вершинам или плоскостям полигонов, а к каждому пикселю наложенной текстурной карты (или к каждому пикселю в системе отображения в настройках движка). Таким образом, при движении света плоские на самом деле участки меша будут иметь тень и блик, как будто на их месте объёмный узор:
![](https://habrastorage.org/getpro/habr/post_images/8fb/758/fe0/8fb758fe0a62c8f51097803f184ffdd2.jpg)
Карта нормалей моего мимика из предыдущего поста.
Достигается это за счёт проекции деталей с модели высокого разрешения на низкополигональную болванку. Другими словами, мы сначала создаём детализированную модель с условными 8 миллионами полигонов (и соответственно 8 миллионами нормалей или даже больше), а потом делаем низкополигональную модель с помощью ретопологии (ручной или алгоритмической перестройки сетки с более низким разрешением и как можно более рациональной сеткой) либо инструментов децимации (сокращения полигонов), если нам не нужна чёткая и красивая сетка. Не забывайте, что в какой-то момент могут понадобиться обе модели: и высокополигональная (highpoly) и низкополигональная (lowpoly), для чего сохраняйте обе.
![](https://habrastorage.org/getpro/habr/post_images/311/ad6/78b/311ad678b5385083267d9436ce92699f.png)
Mid-poly модель и её High-poly версия. Моё.
Не забывайте перед генерацией нормалей сделать развертку для Вашей модели (желательно на лоуполи болванке, чтобы избежать артефактов в местах «сшивания» кусков карты). Качество Вашей развертки будет напрямую влиять на качество отображения Вашей карты нормалей. Так, участки с пересекающейся сеткой наверняка подпортят вид модели и Вашу карму в портфолио.
При этом есть небольшая хитрость. Несмотря на то что обычно советуют делать более-менее равномерную сетку для всей модели (с более-менее одинаковой плотностью и размером полигонов), в среде моделлеров считается хорошим тоном построить сетку так, чтобы отдельные участки имели чуть большую плотность. Обычно это лицо персонажа, руки, морда существа и т.д. То есть, те детали и куски модели, на которые будет много внимания и которые требуют большей подробности.
Аналогично и с картами развертки, на которые будут ориентированы диффузные и нормальные карты: участки «повышенного внимания» делаем большими островами, чем те, кто нам не очень важны.
![](https://habrastorage.org/getpro/habr/post_images/f79/d17/8c8/f79d178c8beec34721c43a97468943f6.png)
Так как эта кираса планируется под создание нескольких вариаций, я оставила остров с передней частью нагрудника побольше, чтобы удобнее было размещать герб в будущем. Моё.
Далее ищем себе программу, в которой будет удобно работать (для меня это Zbrush, для Вас может быть удобен Substance painter, Marmoset toolbag, Blender или Maya Autodesk), и совмещаем обе наших модели так, чтобы они как можно лучше совпадали, но высокополигональная не проваливалась сквозь низкополигональную. Это важно, так как в противном случае, Ваши нормали будут вывернуты, и Вы получите артефакты отображения карты (а в перспективе вылет на рабочий стол при генерации).
Но нужно помнить, что карта нормалей не делает Вашу модель объёмнее. Она только создаёт иллюзию объёма, сама модель так и останется плоской болванкой.
▍ Нормальные алгоритмы
Существует несколько алгоритмов, позволяющих рассчитывать отклонения нормалей и проецировать их с помощью текстурных карт. Самый распространённый способ называется Dot3, и представляет собой кодирование направления вектора нормали по трём осям пространства в соответствующие цвета RGB каналов цвета, причём отклонения осей XYZ соответствуют RGB. То есть, красный канал отвечает за отклонение от 0 (нормали к поверхности) вправо-влево (по оси X), зелёный — вверх-вниз (по оси Y), а синий — по оси Z. А вот дальше начинаются особенности.
Откуда взялась традиция отмечать красным именно ось X, жёлто-зелёным Y, а синим Z, мне найти не удалось. Но абсолютное большинство 3D-программ придерживаются именно такой цветовой схемы в построении осей координат.Дело в том, что каждый графический движок считывает координаты отклонения векторов нормали по-своему, а значит и результаты отображения будут различаться. Более того, Вы заметите сильные различия, даже если сгенерируете нормалмапы с одной и той же модели в разных программах.
Вот, например, одна и та же модель, но зарендеренная в разных движках:
![](https://habrastorage.org/getpro/habr/post_images/cf2/e62/090/cf2e620904da25d8b8a4706cd1da9d9a.png)
Рыцарь собора (cathedral knight) из Dark souls 3.
Существует несколько распространённых подходов к генерации. Кратко расскажем о каждом из них.
Самый общий и простой из них — построение нормалей через пространство касательных или Tangent space. Помните, мы просили запомнить касательные? Вот они и пригодились.
В данной системе координат касательная плоскость к поверхности модели определяется осями X и Y, а ось нормали — Z-ось. Поэтому нормали, сгенерированные по принципу tangent space обычно выглядят синими — основная ось отклонения (выпуклость поверхности) это Z-ось, соответствующая B-каналу RGB-системы:
![](https://habrastorage.org/getpro/habr/post_images/3e1/1df/e4e/3e11dfe4eceeed164a7db65a5eb02334.jpg)
Карта касательных (мое).
Но и здесь возможны проблемы. При генерации нормалей касательных в одной программе и рендеринге в другой Вы иногда можете столкнуться с тем, что тени на Ваших моделях лежат немного не так, как было изначально. В таком случае проверьте инверсию осей отображения нормалей — благо большинство графических 3D-редакторов имеют для этого отдельную кнопку. Если такой кнопки нет — откройте фотошоп и инвертируйте изображение в одном из каналов. У меня бывали случаи, когда приходилось инвертировать два канала — красный и зелёный.
Плюсы генерации нормалей по принципу tangent space в том, что они универсальны. Например, если вы сгенерировали карту нормалей для плоской кирпичной стены, Вы можете применить эту же карту нормалей на любую другую плоскую стену (или любой «плоскатик») с такой же UV-картой и практически ничего при этом не потерять. Модель с картой пространства касательных можно деформировать, и графический движок будет пытаться вычислять нормали соответственно Вашей деформации. Другими словами, стену можно сломать, но отдельные её куски всё так же будут изображать кирпичную кладку, хоть и с искажениями. При желании, Вы можете натянуть текстуру кирпичной стены на яйцо динозавра, и ничего от этого не потерять. Перекраска стены тоже особой роли не сыграет.
![](https://habrastorage.org/getpro/habr/post_images/a4e/32e/565/a4e32e565079a3d0b4ac4aa1a539c31e.png)
Кроме того, тангентные (тангенциальные) нормал мапы можно отражать и разбивать, что не слишком сильно скажется на конечном результате. Да и к сжатию карты для экономии места на диске они вполне терпимы (что особенно важно в игрострое).
![](https://habrastorage.org/getpro/habr/post_images/fb9/fd2/840/fb9fd284090be78c743eca203d66ae56.png)
Слева — карта в разрешении 1028х1028, справа — 4к. Визуальной разницы ни в движке, ни в папке незаметно.
Минусы вытекают из плюсов: в какие условия и в какую точку пространства Вы не поместите свою модель, карта будет читаться одинаково (отличаться будут только направления теней и бликов). Кроме того, касательное пространство не очень любит жёсткие грани, так что при понижении полигонажа при ретопологии и децимации это стоит учитывать. При этом чтение такой карты требует несколько больше ресурсов, хотя и ненамного.
Несколько иначе генерируются модели по методу пространства объекта (object space/ local space/ model space). В ней основной точкой отсчёта, координат отклонения нормалей, считается не касательная к поверхности каждого отдельного элемента рельефа, а центр масс модели относительно всего пространства координат. По цвету такие карты обычно выглядят как серо-буро-малиновое месиво с усилением оттенков красного, синего и зелёного по углам карты и с резкими градиентами по всей текстуре. При этом сила и оттенок цвета будет соответствовать тому, в какую сторону направлена Ваша геометрия относительно глобальных координат модели (также RGB~XYZ по общему правилу).
![](https://habrastorage.org/getpro/habr/post_images/709/8e7/ad5/7098e7ad5e642db04228242e55817a54.jpg)
Объектная карта нормалей (мое).
Плюсы: высокая точность геометрии, «красивое» отображение деталей при динамическом освещении, низкая чувствительность к грубым граням и группам сглаживания, более быстрое чтение карты:
![](https://habrastorage.org/getpro/habr/post_images/8af/29a/26a/8af29a26af151e2b3816441fc6c1aa84.png)
Нормали local space на разных объектах.
Минусы: объект не рекомендуется деформировать, так как любое изменение положения вершины в модели относительно всей сетки приведёт к артефактам отображения, нельзя (вернее, не рекомендуется) отражать карту или использовать её на модели с кардинально другой геометрией, плохо поддаются сжатию (буквально каждый пиксель содержит информацию о цветовом, а значит, геометрическом переходе). Более того, из-за особенностей чтения такой карты при изменении цвета модели через diffuse map может потребоваться дополнительно использовать карту АО (ambient occlusion) для коррекции отображения поверхности, а также набор специальных скриптов и шейдеров:
![](https://habrastorage.org/getpro/habr/post_images/eb5/6f3/4d9/eb56f34d912a022262f8737bbe972f0b.png)
Local (object) space normals в разных местах относительно источника света и оси координат. Одна и та же карта читается по-разному.
![](https://habrastorage.org/getpro/habr/post_images/8af/ce2/539/8afce2539cd7c024f1ec7edc2257197a.png)
Тангенциальные нормали vs объектные нормали.
Нормали пространства камеры (camera space) — вещь настолько редко используемая, что я и сама не слишком много о ней знаю. Могу сказать только, что её иногда используют для создания HDR-пространств и карт окружения (environment map), а также для запекания специфического типа нормалей для рендеринга украшений.
Надо сказать, что в игропроме нет какой-то четкой привязки к тому, какие именно нормали использовать и в каком случае — это строго индивидуальный и технический вопрос, не лишённый толики вкусовщины и экспериментаторства. В одной игре может использоваться сразу 2-3 типа генерации нормалей (например, большая часть моделей в Скайриме «нормализованы» по принципу tangent space, но модели тела и лица персонажей типа «гуманоид» включая аргониан и каджитов имеют запечку object space и прилагающиеся к ним tintmap и шейдеры для коррекции отображения. К тому же тамошние модели инвертированы относительно оси Z наперекор большинству программ. Спрашивается, ну и зачем такой гемор?
![](https://habrastorage.org/getpro/habr/post_images/b89/498/384/b89498384bcbe768171843d4cb9a4f7e.png)
Разные виды нормалей в Скайриме.
Во многих играх комбинируют не только нормали разного типа генерации, но и разные типы имитации объёма. Так, в Bloodborne и Dark souls 3 у некоторых боссов до 6 типов карт, включающих диффузную карту с альфа-каналом прозрачности, карту нормалей с альфа-каналом металлика, спекуляр с силой и цветом металлика, металлик (environment), карта свечения и карта шейдера (шерсти или эффекта). Но игровой движок From software не может поддерживать более 4 текстур на одном меше одновременно, так что модели разбиты на полигруппы (меши) так, чтобы не перегружать движок, но при этом обеспечить максимально плавный переход между соседними мешами с разными текстурами. Быть может, поэтому некоторые участки и арены с боссами в играх «фромов» выглядят достаточно тёмными.
![](https://habrastorage.org/getpro/habr/post_images/c34/58f/b1a/c3458fb1a50b880afcdfcbe23e650fe0.png)
Tangent space normals Dark Souls 3, инвертированные по синему. Тангенциальные карты DS3 и некоторых моделей подземных чудовищ Sekiro, Bloodborne и Elden ring выглядят зелёно-красными. Пусть это Вас не слишком пугает, они всё ещё сделаны в пространстве касательных, но с инвертированным каналом относительно Z (и иногда X, особенно в архивах из вырезанного контента. Видимо, осталось со времен подбора настроек движка).
Кроме того, порой Вы и не поймёте, какого именно типа нормалмап перед Вами, если залезете в архивы игры и сможете-таки распаковать специфическое сжатие текстурных файлов. Так, мы уже говорили о том, что карты нормалей Скайрима содержат дополнительный альфа-канал для карт окружения и металлического блеска, из-за чего они выглядят не лилово-голубыми, как положено тангенциальным картам, а чёрно-синими. При этом, в большинстве своём обычные лилово-голубые карты движок Скайрима (по крайней мере, LE) вполне переваривает и даже отображает, но вот с наложением металлика на такие модели могут возникнуть проблемы (моддер с 10-летним стажем детектед).
Да и в самом игровом движке наличие некоторых карт и их качество может вызывать артефакты и даже приводить к вылетам игры. Так, одновременное наличие карты отражения, свечения и наложение шейдера с прикручиванием эффекта искр к Маледикту из Doom 3: RE в Скайриме привело к крашу игры, хотя в окне редактора всё было в полном порядке.
![](https://habrastorage.org/getpro/habr/post_images/0e1/8a4/f7e/0e18a4f7ebc4c31a833e46f475d86045.png)
Вполне видимый горелый Меледикт в редакторе моделей Скайрима (Nifskope), в Creation kit тоже нареканий не вызывал. Но когда он появляется в игре, то все.
Особенное впечатление производят нормалмапы от некоторых студий. Например, ранние карты нормалей от Ubisoft (создателей Ассассинской саги) выглядят розово-красными. Инверсия каналов цвета при этом не слишком помогает, так что для исправления отображения этих карт приходится перегенерировать их или прогонять через конвертеры, инвертирующие RGB.
![](https://habrastorage.org/getpro/habr/post_images/705/4c6/8b1/7054c68b1a5a057af729d630e1b1961b.png)
Кроме того, есть и другая градация нормалей - эксплицитные (explicit) и усреднённые (averaged). Подробно я на них останавливаться не буду, так как это слишком тонкий вопрос. Скажу только, что в общих случаях обычно применяют explicit normals, так как он более лоялен к искажению деталей, хотя и может выдавать артефакты на краях жёстких граней и в местах разрезов UV, тогда как averaged normals выглядит хорошо на границах, но может сильно искажать высоко выступающие детали, стягивая их к центру меша.
▍ Генерируем. Нормально
Для тех, кто дожил до этого места и не сломал себе моск (или ещё не захотел прибить автора статьи за неточности в описании процессов), приведём несколько практических способов генерации нормалей. Начнём с самого требовательного — с генерации нормалей из хайполи геометрии.
Для этого нам понадобятся:
- Лоуполи модель (желательно в формате obj) (низкополигональная болванка, если нет, то сделаем)
- Хайполи модель (если её нет, сделаем в процессе)
- ZBrush, желательно R21, так как я чаще всего пользуюсь именно им и он наиболее стабилен и максимально лоялен к нулевому скиллу в запекании.
1. Для начала импортируем нашу обж-шку в зибраш. Жмякаем на панели справа (по умолчанию именно там находится панель Tools) на большую кнопку Import и находим нужную модель. Либо довольствуемся базовой сферой (Sphere 3D), выбрав её на той же панельке (главное, не перепутать с ZSphere, специальным инструментом рига и ретопологии):
![](https://habrastorage.org/getpro/habr/post_images/9ce/929/ba8/9ce929ba85d314aa3cf15609090eedee.png)
После загрузки нашей модели вверху слева жмём на иконку Edit, чтобы активировать режим редактирования, и сразу жмём Make Рoly Мesh 3D рядом с кнопкой импорта, чтобы избежать дальнейших проблем.
2. Если у Вашей болванки заранее была создана UV-карта, переходим к следующему пункту.
Если нет, то всё необходимое у нас под рукой: открываем в верхнем меню ZPlugin — UV-master. Далее нужно проверить несколько пунктов.
Для экономии места и времени поместим их под спойлер.
После проверки всех вышеперечисленных пунктов (или проигнорировав оные) жмякаем кнопку Unwrap («развернуть»). Программа на какое-то время «зависнет», под верхними вкладками поясняя, какой именно этап создания развёртки сейчас происходит. Развёртка лоуполи моделей в среднем занимает от полуминуты до нескольких минут в зависимости от сложности модели и количества полигрупп. Иногда по неизвестной причине плагин может зависнуть, и тогда придется нажимать кнопку «развернуть» заново.ТЫК
- Если модель симметричная, то жмём кнопку symmetry, чтобы генератор развёртки попытался расположить острова симметрично.
- Если в Вашей болванке несколько мешей и Вы хотите, чтобы каждому из них соответствовал свой «остров» на текстуре, то переходите на панель Tool, найдите свиток Polygroup и нажмите Auto Group. Зибраш автоматически определит границы мешей и назначит их в полигруппы по местам разрывов. Посмотреть свои полигруппы можно по нажатию иконки PolyF справа от рабочей области.
- Если в процессе импорта Ваша модель «развалилась» (то есть, вершины полигонов в группе сглаживания вдруг отсоединились друг от друга. Да, так бывает и весьма часто), то идём в Tool — Geometry — Modify topology и ищем там пункт Weld points. В большинстве случаев, этого достаточно.
- Если в Вашей модели обнаружились непредусмотренные дыры, то рядом с Weld points ищем кнопку Close Holes. Обычно этого хватает, но иногда в моделях со сложной геометрией эта кнопка начинает «выстилать» модель дополнительным слоем полигонов изнутри. Точного правила для такого эффекта нет, так что каждый случай проверяйте отдельно. Отмена действия в зибраше такая же, как и везде: Ctrl+Z или по ползунку действий над рабочим полем с моделью.
- Если у Вашей модели нет полигрупп, но очень хочется их сделать, да ещё и ровными, то тогда замаскируйте куски модели (зажмите Ctrl и поводите кистью по поверхности либо зажмите Ctrl и потяните из пустой области рабочего поля), перейдите по уже знакомому пути Tools — Polygroup и найдите внизу кнопку Group masked (после этого можно нажать Clear mask или провести с зажатым Ctrl по пустой области). Если хотите разбить ещё больше, щелкните ЛКМ по новообразованной группе с зажатым Ctrl+Shift и повторите процедуру с маскированием и нажатием Group masked. Отменить скрытие групп можно, щелкнув Ctrl+Shift+ЛКМ в пустом месте.
- Если полигруппы Вас не устраивают, и Вы вручную хотите назначить места разрезов на UV-карте, тогда переходите во вкладку Zplugin — UV master и активируйте кнопку Enable control painting. Тогда Вам станут доступны ещё три кнопки — Protect, Attract, Erase (защитить/оставить без разрезов, разрезать по линии и стереть марки соответственно). Ими и раскрашивайте Вашу модель, обозначая красным зоны, которые должны оставаться нетронутыми, синим места разъединения и предпочитаемые швы. Главное, не сильно увлекаться: слишком близко расположенные марки могут сбить программу с толку, а слишком большое или недостаточное количество разрезов приведёт к искажению сетки на карте.
![](https://habrastorage.org/getpro/habr/post_images/ead/1f8/aa7/ead1f8aa7609e8f732ef09b99c5ea6de.png)
Проверить и поправить свою развёртку можно, нажав на панели UVmaster кнопку Flatten. Здесь с развёрткой можно работать как с обычной моделью теми же инструментами. Если развёртка устраивает, возвращаемся к обычному виду с помощью кнопки Unflatten.
3. Лоу-поли болванку с готовой развёрткой теперь нужно обеспечить подробными деталями. Для этого копируем нашу модель (Subtool — duplicate), чтобы сохранить лоу-поли болванку, увеличим плотность сетки с помощью инструмента Tool — Divide (или Ctrl+D). Это поднимет полигонаж примерно в 4 раза за каждое нажатие кнопки (каждый четырёхугольник разбивается на 4 части), количество уровней подразбиения будет записано вверху над ползунком SDiv (subdivides — подразбиения), где вы в любой момент можете переключаться между уровнями детализации. Теперь можно лепить объёмные детали поверх болванки.
![](https://habrastorage.org/getpro/habr/post_images/300/421/7a1/3004217a1c9857d5d3b256a90fdcd448.png)
Примечания:4. Как только Вы наигрались с лепкой или решили, что детализации у Вашей модели достаточно, переходим к генерации карт.
- Если в процессе подразбиения появляются дыры, отмените действие и перейдите в Geometry — Weld points.
- Чтобы сохранить резкость граней, нужно отключить кнопку Smt рядом с кнопкой Divide.
- На слабых компьютерах не рекомендуется делать больше 4-6 млн полигонов (как только вы перешагиваете порог в 1,5 млн, программа уведомит Вас в строке над ползунком истории действий)
- В Зибраше Вы можете одновременно рисовать цветом и выдавливать объем. Для этого на верхней панели нужно активировать кнопки Mrgb или Rgb (рисование материалом и цветом или только цветом) и Zadd/Zsub. Рисование с зажатой кнопкой Alt переключит с режима выдавливания на вдавливание и наоборот, а также заменит цвет на альтернативный (посмотреть выбранные цвета можно под палитрой слева).
- В зибраше есть возможность выбора узора кисти через загрузку альфа-кисти (панель слева — Alpha). Можно выбрать готовую, скачать или сделать самому в фотошопе, нарисовав чёрно-белый узор (черный — нет эффекта, белый — максимальный объем). Работать с альфа-каналом в файле изображения не обязательно, зибраш и без него хорошо читает интенсивность белого.
Если в процессе Вы вдруг удалили самые низкие подразбиения — не страшно. Проверьте «слой» с лоу-поли моделью (которую мы советовали дублировать) на панели Subtool, переместите этот слой вниз (можно просто перетаскиванием строки) и убедитесь, что оба слоя в видимом режиме. Увеличьте подразбиения на лоу-поли модели на такое же количество уровней на панели Geometry. Теперь на панели Tools разверните строку Project, активируйте кнопки Geometry и Color и нажмите Project all. В общих случаях этого должно хватить, в редких надо будет поиграться с ползунками Dist и Mean.
![](https://habrastorage.org/getpro/habr/post_images/dcf/b66/c71/dcfb66c71d2d890db3cf0380ef770d4f.png)
Первой генерируем текстурную диффузную карту (цвет). Для этого идём на панель Tool — Texture map и нажимаем Create — New from polypaint. Текстура запечётся на модели, а вам станет доступна кнопка Clone. Смело жмите её и жмём на появившемся её клоне слева, затем Export. Текстурная карта готова.
Теперь идём на панель Geometry и опускаем все сабдивы до нуля (но не удаляем их!). Снова спускаемся вниз по боковой панели, находим кнопку Normal map и жмём Create normal map.
![](https://habrastorage.org/getpro/habr/post_images/a20/392/682/a20392682ccbf0ace2da0a64df9b24e1.png)
По умолчанию в браше активна кнопка Tangent и карта нормалей генерируется по принципу касательных. Её можно отключить, и Вы получите объектную карту нормалей.
![](https://habrastorage.org/getpro/habr/post_images/bd4/fb9/349/bd4fb9349d49ab52bbf0f780cca4d4df.png)
Слева — сгенерированная карта по принципу tangent space, слева — object space.
Все. Наша нормаль запеклась. Повторяем нажатие кнопки Clone и Export.Здесь же можем выбрать способ запечения нормалей (тангенциальный или адаптивный), а также сгладить или отразить нормали или переключить вектора XY.
▍ Хитрость — это нормально!
Бывает так, что уже после запечения карты на модели Вы заметили, что чего-то не хватает. Или в последний день пришли правки, в которых заказчик потребовал в срочном порядке налепить или замазать лишнюю заклёпку на корпусе или добавить царапин на кирасу. А нормального компа под рукой нет, да и перегенерировать десяток карт не очень-то хочется. Есть ли какой-то выход из положения? Конечно, есть!
Вообще, использовать вместо запечённых карт автоматическую генерацию — не слишком-то приветствуется в профессиональной среде, но нет-нет, да и мастера моделлинга прибегают к подобным «низменным» уловкам. А уж нам-то с Вами и вовсе не зазорно.
![](https://habrastorage.org/getpro/habr/post_images/91e/eed/605/91eeed60582af00ba8b49cd80aa3cfcd.png)
Слева направо: запечённая в ZBrush карта нормали мятой кирасы, сгенерированная в PS карта из диффузной, объединённая и отредактированная конечная карта.
Главный и самый близкий друг любого моделлера — Photoshop. В нем Вы сможете не только подправить цветовую карту, но и подработать карту нормалей.
Да, это кощунство, но в начале своего пути как моделлера, я не стеснялась вручную дорисовывать пурпурные и синие участки на карте нормалей, чтобы исправить отображение объема и прибавлять контрастность для усиления резкости деталей. Да, не всегда это выглядело хорошо, но в самых простых графических движках на базе OpenGL, DirectX и некоторых других это работает до сих пор.
![](https://habrastorage.org/getpro/habr/post_images/177/a72/88a/177a7288aa28d4e5c416250039a53f4c.jpg)
Отредактированные в фотошопе нормали кирасы. Моё.
В целом, никто не мешает Вам взять две готовые карты нормалей и в фотошопе перенести кусок одной на другую, или вообще наложить одну полупрозрачную поверх другой. В некоторых случаях я именно так и делаю. Но надо учитывать риск появления артефактов в том графическом движке, где будет проходить финальный рендеринг.
![](https://habrastorage.org/getpro/habr/post_images/789/8d1/dba/7898d1dbadeb461fa29601adf37975eb.png)
Nvidia normal map фильтр для фотошопа.
Кроме того, сейчас есть хороший плагин-фильтр для фотошопа (а также самостоятельная программа): Nvidia Tools (новая версия с официального сайта). Он позволяет кроме прочего генерировать карты нормалей весьма хорошего качества исходя из соотношения света, тени и яркости диффузной карты или карты высот. При этом каждая неровность будет отображена на нормалмапе. В плагин встроено множество настроек и режимов, включая инвертирование по цветовым каналам, учитывание слоёв изображения, настройку силы и резкости выдавливаний и конверсию каналов и всей карты нормалей в карту высот:
![](https://habrastorage.org/getpro/habr/post_images/8d9/3fd/fda/8d93fdfda70aa666b3a81900a446ce1d.png)
Но таким образом Вы можете получить только тангенциальную карту. При этом, сгенерированная на основе изображения, карта нормалей не будет учитывать большие перепады высот. Так что рекомендуем использовать её только для создания и добавления мелких (по высоте над поверхностью) деталей.
Нечто похожее в плане самостоятельных программ — ShaderMap Pro. В него встроен целый ряд настроек генерации карт, включая карту нормалей, дисплейс карту и спекуляры, а также настройку глубины, инверсию осей и перегенерацию новой карты нормалей на основе загруженной.
![](https://habrastorage.org/getpro/habr/post_images/4c9/3c8/77f/4c93c877f701adf6ab6d58366669514a.png)
Кроме нее я использую ещё Crazybump, так как он лучше генерирует дисплейс-карты, но хуже работает с нормалями.
Существует также целый ряд бесплатных программ и сайтов с автоматической генерацией карт.
В первую очередь, вам поможет бесплатный сайт. Сюда Вы сможете загрузить изображение условной гайки или шестерёнки и получить на выходе normal и/или displacement карту.
![](https://habrastorage.org/getpro/habr/post_images/589/c92/b93/589c92b9304c4cf7525d201ea6d56c13.png)
Схожий принцип работы у сайта Smartnormal. Он также поддерживает генерацию карт нормалей из диффузных, и инвертирование по осям, а также сглаживание, размытие краёв и силу выдавливания. В принципе, эти два сайта пока что являются лучшими в своём роде.
![](https://habrastorage.org/getpro/habr/post_images/fd5/31c/a2f/fd531ca2f5f427f7d94d8dc509ec1905.png)
Сайт не очень удобно отображает текстуры (в реальном разрешении, без подгонки), так что работать с настройками бывает проблематично.
Некоторые извращенцы и вовсе генерируют карты нормалей внутри игровых движков, но я к ним не отношусь, поэтому ничего путного про это рассказать не могу.
Зато точно могу сказать, что какого-то единого идеального правила или универсального алгоритма создания и работы с картами нормалей до сих пор не существует, поэтому не стесняйтесь экспериментировать и пробовать что-то новенькое, даже если оно покажется Вам совершенно безумным.
Конкурс статей от RUVDS.COM. Три денежные номинации. Главный приз — 100 000 рублей.
![](https://habrastorage.org/webt/sz/7j/pf/sz7jpfj8i1pa6ocj-eia09dev4q.png)