Раз нормально, два нормально… Или имитация объема в плоскости

kzx0iijogf5texbjrfqhhc8q0rs.jpeg


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

▍ Поговорим о нормальных картах.

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

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


▍ Что нормально, а что нет?


Обычный набор текстур босса из Bloodborne:

3021b35c685050f3adc9238453851379.pngЕсли Вы интересуетесь 3D-моделированием, то наверняка хотя бы раз сталкивались с понятием карт (map). Причём слово «карта» имеет очень много дополнительных уточнений: диффузная карта, карта наложения, нормальная карта, карта смещения, карта высот, карта цвета, альфа-карта, карта шейдера, карта свечения, карта блеска, карта света, карта подповерхностного рассеивания и т.п.

Всё это — дополнительные элементы модели, так или иначе, улучшающие её внешний вид. По сути своей, текстурные карты — графические файлы («картинки») с соответствующими расширениями (bmp, png, tga, jpg, dds и т.п.), в слоях или строках которых зашифрован не только цвет, но и какая-либо дополнительная информация (наличие и сила альфа-канала, проще говоря, прозрачности; отклонения света, сила блеска, насыщенность и т.п.).

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

СПОЙЛЕР: Карты бывают разные — синие, белые, красные
Карт в 3D-моделировании великое множество, и в каждом графическом движке они имеют свои виды и особенности. Поэтому мы постараемся кратко пояснить, что какая карта делает. Но имейте в виду, что в Вашем конкретном движке карты и соответствующие им кнопки могут незначительно отличаться по названию и функции.

Самая важная карта — карта наложения или UV-map. Она определяет как именно текстура будет ложиться на Вашу модель и какие полигоны будут соответствовать «островам» на текстуре. UV-карта и информация о наложении хранится в файле самой модели (обычно), и изредка в специальных форматах библиотек наложения или программных информационных файлах, а в редких случаях — ещё и в составе алгоритма шейдера (программного сценария графической визуализации). 

af05c41fbcf6438fbcf21650ae252b93.png
UV-развертка и модель снаряжения. Сделано мной.

Диффузная карта (diffuse map/ color map) — это карта цвета или раскраска модели. Она пришла на смену объектной заливке и раскрашиванию полигонов моделей напрямую. Долгое время это была единственная карта, применимая к модели (помимо UV), и до сих пор многие игры (особенно мобильные, где максимально важна экономия пространства памяти и вычислительных ресурсов) обходятся только ею. Умелая работа с диффузной картой действительно способна заменить в какой-то степени другие карты, но всё же её часто бывает недостаточно.

7ba1023e41364bfb52f4fc01c456befe.png
Diffuse map сама по себе и на снаряжении. Моё.

Альфа-карта, просто альфа или карта прозрачности (alpha / transparent map) — карта, отвечающая за чтение прозрачности на текстуре. В игровых движках эту функцию на себя часто берёт диффузная карта, в которую встроен альфа-канал (наверняка Вы видели эту кнопку в фотошопе). Он может быть как действительно прозрачным (png файлы), так и просто нести информацию о прозрачности (dds и tga форматы), не отображаясь в файловой системе компьютера, как прозрачный.

В некоторых программах (например, в Keyshot или Daz studio) Вам иногда потребуется альфа-карта как отдельный файл (для сложных текстур, например, волос и ресниц). В таком случае Ваша карта будет выглядеть чёрно-белой, где чёрный цвет означает 100% прозрачность, а белый — 100% непрозрачность. Причём для Даза и Кейшота даже необязательно наличие именно альфа-канала на альфа-карте, главное соблюсти цветовую пропорцию, да, всё сложно. А как Вы хотели?

43f4e5639002634a907dd62d34f4c297.png
Альфа-карта прозрачности для волос. Моё.

Карта блеска (specular map) — карта, ответственная за силу и иногда цвет блеска. Как нетрудно догадаться, чёрный цвет означает отсутствие блеска, белый — его максимум (в некоторых движках может потребоваться вмешательство альфа-канала, но в общем случае это не нужно). Кроме оттенков чёрного и белого спекуляры могут нести и другие цвета. Например, Разверстый дракон в игре Dark souls блестит оттенками синего и фиолетового (если Вы его успеете рассмотреть, конечно).

1af629f4e68aee3c4e3d653b3ca484f8.png
Карта блеска (specular) и её действие в кейшоте (тоже моё).

2efb73e746d1338f472677a590979473.png
Цветной спекуляр разверстого дракона из Dark souls 3.

Карта свечения (emission map/ glowing map) — карта, название которой прямо отображает её функции. Как нетрудно догадаться, чёрный цвет означает отсутствие свечения, чисто белый — максимальное свечение. Но большинство игровых движков читают не только силу белого, но и все доступные оттенки цветовых каналов, позволяя раскрасить условного дракона во все цвета радуги. При этом некоторые графические движки позволяют читать карту свечения как источник света — то есть, создавать от него блики на других частях модели и других моделях (например, тот же Кейшот или движок Скетчфаба).

686bccb66dcbb659d32205328d2519d5.png
Карты свечения и их действие на примере Стража древних богов из Bloodborne.

Карта пространственного отражения (environmental map/ metallicity map). Этот термин имеет два значения: карта наложения отражения (отвечает за то, какие участки модели будут иметь это свойство) и собственно текстура отражения (также environment map/ cubemap/ metallmap/ sphere map и т.п.). В первом случае существуют разные подходы к её осуществлению, обычно используют очень любимый нами альфа-канал, добавляя его к различным другим текстурам. Например, альфа-канал нормали в Скайриме отвечает за наложение этого самого отражения, если в настройках nif-модели прикрепить соответствующий металлик или отражение. При этом сила блеска отражения берётся с карты — пометка _m (metalicity). 

76f3c6d7a40b1f5275b34542005d6221.png
Карты металличности, цвета и нормалей из TES V: Skyrim. На диффузной карте видны артефакты альфа-канала от криворукого разработчика. Вообще, про кривизну рук разрабов Скайрима у меня много хороших слов. Но о грустном как-нибудь в другой раз.

Что-то подобное есть и в Dark souls 3, где в альфа-канале нормали закодированы участки металлического блеска и карты окружения, а в аномально светлом спекуляре — сила и оттенок этого блеска.

4357b2e42526417d6dcc979748b3219e.png
Карты для кирасы рыцарского сета из Dark Souls 3 (сверху вниз: диффузная, карта нормалей и спекуляр). Сбоку карта окружения (с фрагментом неба) и её отражение на кирасе. Отметим, что карты окружения в DS3 динамические, и сменяют друг друга по мере продвижения по локации. 

Карта подповерхностного рассеяния и просвечивания (translucent map) — немного схожи с предыдущими картами. Эти карты отвечают за то, как модель будет выглядеть «на просвет». Если Вам кажется, что это какая-то бесполезная функция или вообще аналог прозрачности, то вы ошибаетесь. Посмотрите через свою руку на просвет (на лампу или солнце) и Вы увидите, что пальцы и перепонки у их основания словно светятся, просвечивают. То же самое и с полупрозрачными минералами (кварц, яшма, янтарь и т.п.), с частями тела людей и даже листьями. 

96f3f52786f4a340e8d7c77a3b8a9091.png
Карта подсвечивания для женских персонажей и карта просвечивания для крыла драконов в TES V: Skyrim.

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

Карта света и карта оттенка (lightmap/ambient occlusion map/ tintmap) — карта, отвечающая за то, как Ваша модель будет реагировать на свет. Некоторые движки читают эти карты подобно картам рассеяния, придавая эффект просвечивания, некоторые просто читают её как маску, добавляя оттенки и световые блики к диффузной карте. Изначально эта карта служила для создания светотени, создавая эффекты затенения и освещённости на модели для экономии ресурсов. 

492209874df85ce738c9620b0988fcd4.png
Честно говоря, я не очень помню, откуда эта модель, так как предоставил её друг, для наглядности. Кажется, из Bless online. Слева модель без карт света, справа — с ними, отображаемые тени от лайтмапа делают стилизованную модельку реалистичнее и приятнее глазу.

Сейчас для этого иногда используют более продвинутую версию — карту пространственного освещения (ambient occlusion map), которая, по сути, является гибридом спекуляра и лайтмапа, имитируя свет, тень и блики. Однако, в отличие от лайтмапа, АО не заменяет собой эффект освещения, а читается графическим движком вместе с тенями от источника света, придавая глубину теням для экономии производительности в больших сценах.

В некоторых случаях карта оттенка имеет вид сине-красно-зеленых пятен (как, например, в Witcher 3 или Raid Shadow legends) и сочетает в себе карту оттенков, карту блеска и карту наложения пространственного отражения, закодированные в разных цветах.

916c43a4ba7f480a8e0868c90e2c9d52.png
Слева: карта Ambient occlusion для сцены боя из игры Raid: Shadow legends, справа вверху: рендер внутриигровым движком (на базе Unity), справа внизу — рендер без окклюзии. Хорошо видно, что карта света и тени из АО создаёт эффект объёма и придаёт живости рендеру. Хочу заметить, что для сцен окружения эта игра использует только диффуз и окклюзию, экономя место и производительность.

Карта смещения (displacement map): чёрно-белая карта, которую графический движок игры или редактора читает, как искажение поверхности модели. В отличие от нормалмапа, дисплейс-карты не имитируют объём, а непосредственно «показывают» движку, как именно должна выглядеть модель, благодаря чему на финальном рендере модель действительно будет иметь объём, а не его иллюзию. Но работая с дисплейс-картами важно учитывать множество нюансов, начиная от того что каждый движок читает их силу и соотношение цветов по-своему, и заканчивая тем, что дисплейс-карты — это векторная информация, и изменение размера модели или положения её в пространстве могут значительно исказить финальный вид.

d323084211c7099026eef1c6f1c93378.png
Слева — тестовый рендер с включёнными displacement и emission картами, справа — рабочий режим без дополнительных карт (только с диффузной). Робот мой.

Карта высоты (bumpmap) — первый предшественник дисплейс-карт и карт нормалей. Чёрно-белая текстура, в которой сила белого определяет силу «выдавливания» объёма на поверхности модели. Сейчас бампмапы как таковые почти не используют (разве что в единичных проектах или в составе шейдера), предпочитая им более продвинутые карты смещения и нормалей, так что сам термин bumpmap сейчас употребляют часто как синонимичный displacement и normalmap, хотя это и не совсем верно.

Нормальная карта (правильнее говорить «карта нормалей», normal map) — карта, имитирующая объём. Она создаёт видимость неровной поверхности за счёт переходов света и тени. Подробнее о тонкостях отображения нормалей мы поговорим позже. 

  • Что такое нормали?
  • В отличие от повседневной жизни, в математике нормаль определяется отнюдь не общественным сознанием.
  • Нормаль в 3D-моделировании — это перпендикуляр к поверхности модели (обычно к вершине многоугольника, но на самом деле к любой точке поверхности). Если Вы помните школьный курс геометрии, то должны знать, что есть такое понятие, как касательная (линия или плоскость). Так вот, если провести касательную плоскость к поверхности модели в выбранной точке, а потом в этой же точке опустить перпендикуляр к поверхности касательной, это и будет нормаль.
  • Запомните касательные! Они нам ещё пригодятся!

7cefc9c43657128198c279b715fc184a.png3ed6dd713d957313e237f0235dd377bf.png

В 3D-моделировании вектор нормали проводится к каждой точке поверхности модели (в зависимости от работы движка: к каждой вершине, каждому отдельно взятому полигону или каждой точке меша в пространстве. Последнее сейчас наиболее распространено, но затратно по ресурсам вычислительной техники). Совокупность направлений этих векторов визуализируется как перепады поверхности модели: выступы, впадины и заломы. Если разница между направлениями двух соседних векторов большая, то и перепад будет казаться более резким. Соответственно, чем больше полигонов и вершин, и чем больше разница в векторах нормалей, тем подробнее поверхность модели и тем разнообразнее детализация.

12f3d7c88c3f9a4a4991f377ca1b516b.png
Нормали к поверхности на основе вершин в высокополигональной модели. Да, это Клавикус Вайл (мое).

Примечание: в современных графических движках есть такая функция как «сглаживание» (smoothing). Она отвечает за то, насколько «грубо» читается переход от одной нормали к другой (от одного полигона к другому или насколько сильно искажён полигон). 


2c8e5cca61f06b1c98bf57a38c9f3647.png
Иногда для лучшего сглаживания моделей придется разбивать полигоны на треугольники.

При низком сглаживании модель кажется рубленной или мятой, при высоком замыленной. Единый меш (кусок модели с объединёнными вершинами полигонов), к которому применено сглаживание с заданными настройками, называется группой сглаживания (smoothing group):

b0f92d1ecc019d8f9663729c37212f9d.png
Более сглаженная и менее сглаженная геометрия лапки. Моделька моя.

При этом важно понимать, что вычисляется переход между нормалями только соседних вершин в составе меша (единого куска поверхности модели) или группы сглаживания:

fa0aa6ae89028b498f26cb2cc79f5edb.png
Сглаженная и не сглаженная сферы.

Если вершины полигонов в меше («теле» модели) не объединены, то есть, каждый полигон сам по себе, то для каждой вершины каждого отдельного меша нормаль считается отдельно, из-за чего модель также кажется рубленой и грубой.

Однако если сейчас многие киностудии и даже игроделы могут себе позволить сделать модель с парой миллионов полигонов и не сжечь при этом видеокарту (хотя некоторые игры от Square enix всё-таки сожгут), то на заре игропрома такой роскошью не могли похвастаться даже крупные студии. Да и сейчас такое выглядит не слишком-то разумно и экономично. Как выходили из положения тогда?

▍ Намальна? Намальна!


Если нормали к поверхности модели определяют, как на нее ложится свет, то нельзя ли обмануть визуализацию?

Можно. Причём для этого существует великое множество способов — начиная с обмана зрения с помощью карт цвета и заканчивая специальными программными алгоритмами пост-обработки (шейдерами). Но сегодня мы ограничимся картами нормалей.

Точно не известно, кто именно был пионером применения техники создания карт нормалей в играх (хотя точно известно, что распространение эта технология получила благодаря приставке Sega Dreamcast, первой игровой консоли со специальными алгоритмами чтения карт). 

Однако известно, что первым подобный алгоритм описал Джеймс Ф. Блин в 1978 году (эксперт по компьютерной графике лаборатории НАСА). Позднее его идею развили Кришнамурти и Левой, представив свою идею на ежегодной выставке-конференции SIGGRAPH в 1996 году. Там они впервые представили практический способ построения карт смещения в NURBS (неравномерный рациональный базисный сплайн, проще говоря — математическая модель, состоящая из совокупности кривых). Но практически применили перенос детализации с высокополигональной модели на низкополигональную болванку только спустя два года, когда почти одновременно вышли статьи Коэна и Сигнони (не уверена, как правильно читается фамилия), описывающие процесс хранения данных о детализации поверхности в текстурной карте и собственно процесс «запекания» и проекции деталей с высокополигональной сетки на низкополигональную. Тогда же и был придуман алгоритм, которым пользуются до сих пор: кодирование отклонения векторов нормали в цвет.

Карта нормалей или normal map — специфическая текстурная карта, благодаря которой свет в 3D-программе или графическом движке игры понимает, под каким углом ему нужно отражаться от поверхности модели. 

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

8fb758fe0a62c8f51097803f184ffdd2.jpg
Карта нормалей моего мимика из предыдущего поста.

Достигается это за счёт проекции деталей с модели высокого разрешения на низкополигональную болванку. Другими словами, мы сначала создаём детализированную модель с условными 8 миллионами полигонов (и соответственно 8 миллионами нормалей или даже больше), а потом делаем низкополигональную модель с помощью ретопологии (ручной или алгоритмической перестройки сетки с более низким разрешением и как можно более рациональной сеткой) либо инструментов децимации (сокращения полигонов), если нам не нужна чёткая и красивая сетка. Не забывайте, что в какой-то момент могут понадобиться обе модели: и высокополигональная (highpoly) и низкополигональная (lowpoly), для чего сохраняйте обе.

311ad678b5385083267d9436ce92699f.png
Mid-poly модель и её High-poly версия. Моё.

 Не забывайте перед генерацией нормалей сделать развертку для Вашей модели (желательно на лоуполи болванке, чтобы избежать артефактов в местах «сшивания» кусков карты). Качество Вашей развертки будет напрямую влиять на качество отображения Вашей карты нормалей. Так, участки с пересекающейся сеткой наверняка подпортят вид модели и Вашу карму в портфолио. 

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

Аналогично и с картами развертки, на которые будут ориентированы диффузные и нормальные карты: участки «повышенного внимания» делаем большими островами, чем те, кто нам не очень важны.

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

Далее ищем себе программу, в которой будет удобно работать (для меня это Zbrush, для Вас может быть удобен Substance painter, Marmoset toolbag, Blender или Maya Autodesk), и совмещаем обе наших модели так, чтобы они как можно лучше совпадали, но высокополигональная не проваливалась сквозь низкополигональную. Это важно, так как в противном случае, Ваши нормали будут вывернуты, и Вы получите артефакты отображения карты (а в перспективе вылет на рабочий стол при генерации).

Но нужно помнить, что карта нормалей не делает Вашу модель объёмнее. Она только создаёт иллюзию объёма, сама модель так и останется плоской болванкой.

▍ Нормальные алгоритмы


Существует несколько алгоритмов, позволяющих рассчитывать отклонения нормалей и проецировать их с помощью текстурных карт. Самый распространённый способ называется Dot3, и представляет собой кодирование направления вектора нормали по трём осям пространства в соответствующие цвета RGB каналов цвета, причём отклонения осей XYZ соответствуют RGB. То есть, красный канал отвечает за отклонение от 0 (нормали к поверхности) вправо-влево (по оси X), зелёный — вверх-вниз (по оси Y), а синий — по оси Z. А вот дальше начинаются особенности.

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

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

Вот, например, одна и та же модель, но зарендеренная в разных движках:

cf2e620904da25d8b8a4706cd1da9d9a.png
Рыцарь собора (cathedral knight) из Dark souls 3.

Существует несколько распространённых подходов к генерации. Кратко расскажем о каждом из них.
Самый общий и простой из них — построение нормалей через пространство касательных или Tangent space. Помните, мы просили запомнить касательные? Вот они и пригодились.

В данной системе координат касательная плоскость к поверхности модели определяется осями X и Y, а ось нормали — Z-ось. Поэтому нормали, сгенерированные по принципу tangent space обычно выглядят синими — основная ось отклонения (выпуклость поверхности) это Z-ось, соответствующая B-каналу RGB-системы:

3e11dfe4eceeed164a7db65a5eb02334.jpg
Карта касательных (мое).

Но и здесь возможны проблемы. При генерации нормалей касательных в одной программе и рендеринге в другой Вы иногда можете столкнуться с тем, что тени на Ваших моделях лежат немного не так, как было изначально. В таком случае проверьте инверсию осей отображения нормалей — благо большинство графических 3D-редакторов имеют для этого отдельную кнопку. Если такой кнопки нет — откройте фотошоп и инвертируйте изображение в одном из каналов. У меня бывали случаи, когда приходилось инвертировать два канала — красный и зелёный.

Плюсы генерации нормалей по принципу tangent space в том, что они универсальны. Например, если вы сгенерировали карту нормалей для плоской кирпичной стены, Вы можете применить эту же карту нормалей на любую другую плоскую стену (или любой «плоскатик») с такой же UV-картой и практически ничего при этом не потерять. Модель с картой пространства касательных можно деформировать, и графический движок будет пытаться вычислять нормали соответственно Вашей деформации. Другими словами, стену можно сломать, но отдельные её куски всё так же будут изображать кирпичную кладку, хоть и с искажениями. При желании, Вы можете натянуть текстуру кирпичной стены на яйцо динозавра, и ничего от этого не потерять. Перекраска стены тоже особой роли не сыграет. 

a4e32e565079a3d0b4ac4aa1a539c31e.png

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

fb9fd284090be78c743eca203d66ae56.png
Слева — карта в разрешении 1028×1028, справа — 4к. Визуальной разницы ни в движке, ни в папке незаметно.

Минусы вытекают из плюсов: в какие условия и в какую точку пространства Вы не поместите свою модель, карта будет читаться одинаково (отличаться будут только направления теней и бликов). Кроме того, касательное пространство не очень любит жёсткие грани, так что при понижении полигонажа при ретопологии и децимации это стоит учитывать. При этом чтение такой карты требует несколько больше ресурсов, хотя и ненамного.

Несколько иначе генерируются модели по методу пространства объекта (object space/ local space/ model space). В ней основной точкой отсчёта, координат отклонения нормалей, считается не касательная к поверхности каждого отдельного элемента рельефа, а центр масс модели относительно всего пространства координат. По цвету такие карты обычно выглядят как серо-буро-малиновое месиво с усилением оттенков красного, синего и зелёного по углам карты и с резкими градиентами по всей текстуре. При этом сила и оттенок цвета будет соответствовать тому, в какую сторону направлена Ваша геометрия относительно глобальных координат модели (также RGB~XYZ по общему правилу). 

7098e7ad5e642db04228242e55817a54.jpg
Объектная карта нормалей (мое).

Плюсы: высокая точность геометрии, «красивое» отображение деталей при динамическом освещении, низкая чувствительность к грубым граням и группам сглаживания, более быстрое чтение карты:

8af29a26af151e2b3816441fc6c1aa84.png
Нормали local space на разных объектах.

Минусы: объект не рекомендуется деформировать, так как любое изменение положения вершины в модели относительно всей сетки приведёт к артефактам отображения, нельзя (вернее, не рекомендуется) отражать карту или использовать её на модели с кардинально другой геометрией, плохо поддаются сжатию (буквально каждый пиксель содержит информацию о цветовом, а значит, геометрическом переходе). Более того, из-за особенностей чтения такой карты при изменении цвета модели через diffuse map может потребоваться дополнительно использовать карту АО (ambient occlusion) для коррекции отображения поверхности, а также набор специальных скриптов и шейдеров:

eb56f34d912a022262f8737bbe972f0b.png
Local (object) space normals в разных местах относительно источника света и оси координат. Одна и та же карта читается по-разному.

8afce2539cd7c024f1ec7edc2257197a.png
Тангенциальные нормали vs объектные нормали.

Нормали пространства камеры (camera space) — вещь настолько редко используемая, что я и сама не слишком много о ней знаю. Могу сказать только, что её иногда используют для создания HDR-пространств и карт окружения (environment map), а также для запекания специфического типа нормалей для рендеринга украшений.

Надо сказать, что в игропроме нет какой-то четкой привязки к тому, какие именно нормали использовать и в каком случае — это строго индивидуальный и технический вопрос, не лишённый толики вкусовщины и экспериментаторства. В одной игре может использоваться сразу 2–3 типа генерации нормалей (например, большая часть моделей в Скайриме «нормализованы» по принципу tangent space, но модели тела и лица персонажей типа «гуманоид» включая аргониан и каджитов имеют запечку object space и прилагающиеся к ним tintmap и шейдеры для коррекции отображения. К тому же тамошние модели инвертированы относительно оси Z наперекор большинству программ. Спрашивается, ну и зачем такой гемор?

b89498384bcbe768171843d4cb9a4f7e.png
Разные виды нормалей в Скайриме.

Во многих играх комбинируют не только нормали разного типа генерации, но и разные типы имитации объёма. Так, в Bloodborne и Dark souls 3 у некоторых боссов до 6 типов карт, включающих диффузную карту с альфа-каналом прозрачности, карту нормалей с альфа-каналом металлика, спекуляр с силой и цветом металлика, металлик (environment), карта свечения и карта шейдера (шерсти или эффекта). Но игровой движок From software не может поддерживать более 4 текстур на одном меше одновременно, так что модели разбиты на полигруппы (меши) так, чтобы не перегружать движок, но при этом обеспечить максимально плавный переход между соседними мешами с разными текстурами. Быть может, поэтому некоторые участки и арены с боссами в играх «фромов» выглядят достаточно тёмными.

c3458fb1a50b880afcdfcbe23e650fe0.png
Tangent space normals Dark Souls 3, инвертированные по синему. Тангенциальные карты DS3 и некоторых моделей подземных чудовищ Sekiro, Bloodborne и Elden ring выглядят зелёно-красными. Пусть это Вас не слишком пугает, они всё ещё сделаны в пространстве касательных, но с инвертированным каналом относительно Z (и иногда X, особенно в архивах из вырезанного контента. Видимо, осталось со времен подбора настроек движка).

Кроме того, порой Вы и не поймёте, какого именно типа нормалмап перед Вами, если залезете в архивы игры и сможете-таки распаковать специфическое сжатие текстурных файлов. Так, мы уже говорили о том, что карты нормалей Скайрима содержат дополнительный альфа-канал для карт окружения и металлического блеска, из-за чего они выглядят не лилово-голубыми, как положено тангенциальным картам, а чёрно-синими. При этом, в большинстве своём обычные лилово-голубые карты движок Скайрима (по крайней мере, LE)  вполне переваривает и даже отображает, но вот с наложением металлика на такие модели могут возникнуть проблемы (моддер с 10-летним стажем детектед). 

Да и в самом игровом движке наличие некоторых карт и их качество может вызывать артефакты и даже приводить к вылетам игры. Так, одновременное наличие карты отражения, свечения и наложение шейдера с прикручиванием эффекта искр к Маледикту из Doom 3: RE в Скайриме привело к крашу игры, хотя в окне редактора всё было в полном порядке.

0e18a4f7ebc4c31a833e46f475d86045.png
Вполне видимый горелый Меледикт в редакторе моделей Скайрима (Nifskope), в Creation kit тоже нареканий не вызывал. Но когда он появляется в игре, то все.

Особенное впечатление производят нормалмапы от некоторых студий. Например, ранние карты нормалей от Ubisoft (создателей Ассассинской саги) выглядят розово-красными. Инверсия каналов цвета при этом не слишком помогает, так что для исправления отображения этих карт приходится перегенерировать их или прогонять через конвертеры, инвертирующие RGB.
7054c68b1a5a057af729d630e1b1961b.png
Кроме того, есть и другая градация нормалей —  эксплицитные (explicit) и усреднённые (averaged). Подробно я на них останавливаться не буду, так как это слишком тонкий вопрос. Скажу только, что в общих случаях обычно применяют explicit normals, так как он более лоялен к искажению деталей, хотя и может выдавать артефакты на краях жёстких граней и в местах разрезов UV, тогда как averaged normals выглядит хорошо на границах, но может сильно искажать высоко выступающие детали, стягивая их к центру меша.

▍ Генерируем. Нормально


Для тех, кто дожил до этого места и не сломал себе моск (или ещё не захотел прибить автора статьи за неточности в описании процессов), приведём несколько практических способов генерации нормалей. Начнём с самого требовательного — с генерации нормалей из хайполи геометрии.

Для этого нам понадобятся:  

  • Лоуполи модель (желательно в формате obj) (низкополигональная болванка, если нет, то сделаем)
  • Хайполи модель (если её нет, сделаем в процессе)
  • ZBrush, желательно R21, так как я чаще всего пользуюсь именно им и он наиболее стабилен и максимально лоялен к нулевому скиллу в запекании.


1. Для начала импортируем нашу обж-шку в зибраш. Жмякаем на панели справа (по умолчанию именно там находится панель Tools) на большую кнопку Import и находим нужную модель. Либо довольствуемся базовой сферой (Sphere 3D), выбрав её на той же панельке (главное, не перепутать с ZSphere, специальным инструментом рига и ретопологии):

9ce929ba85d314aa3cf15609090eedee.png

После загрузки нашей модели вверху слева жмём на иконку Edit, чтобы активировать режим редактирования, и сразу жмём Make Рoly Мesh 3D рядом с кнопкой импорта, чтобы избежать дальне

© Habrahabr.ru