Что такое normal maps

Гайд по бейкингу. Важная теория: часть 2

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

Если просто, то это перпендикуляр к поверхности. По нему движок определяет, как от поверхности будет отражаться свет.

Луч света отражается от поверхности симметрично. Если луч падает под углом 45 градусов слева, он отразится под таким же углом и продолжит свое движение вправо.

Еще одна деталь: если две сшитых плоскости находятся под углом относительно друг друга, и их нормали смотрят строго перпендикулярно по отношению к плоскости — их стык будет жестким. Условно говоря, они будут выглядеть как две отдельные поверхности.

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

Так, с помощью редактирования нормалей, можно симулировать трехмерные эффекты на плоскости. На этом принципе редактирования информации о нормалях объекта устроена работа normal map. Только в этом случае данные записываются в RGB текстуру и наносится на объект через материал.

Информация в карты нормалей перепекается с детализированного high poly объекта. Для этого нужны low poly версия модели и её high poly аналог. High poly зачастую отличается сглаженными углами и большей проработкой деталей. Всё зависит от ситуации, но для начала понимания этих различий будет достаточно.

Какую задачу выполняет Low poly модель при запекании? Помимо UV развертки, которая нужна для объяснения программе куда и какой элемент high poly модели запекать на карте нормалей, low poly используется для создания Cage.

Cage — это в какой-то степени копия Low poly модели, которая расширяется по нормалям объекта. Затем, из cage внутрь проецируются лучи, которые захватывают все high poly элементы, попавшие в зону cage, и перепекают их на карту нормалей.

Cage — лишь один из подходов к запеканию, в следующих статьях мы разберем другие способы и расскажем об их достоинствах и недостатках.

От битности зависит количество оттенков, которое может быть записано в изображении. 24-битное изображение может записать 8 бит, или 256 значений в каждый канал. 256 значений обычно достаточно для текстур типа diffuse, specular или gloss map, потому что они используют более широкий спектр цветов, и на них не нужно четко изображать слабые градиенты.

Если утрировать, битность определяет количество доступных промежуточных оттенков на изображении. Чем выше битность — тем больше доступно оттенков.

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

Самый распространенный тип карты нормалей. Она адаптирует направление нормалей вершин объекта, в зависимости от положения объекта в пространстве. Таким образом, нормали объекта отображаются корректно при любом его положении в пространстве. Из-за различий в алгоритмах отображения карт нормалей, Tangent Space Normal разделяется на два типа: DirectX и OpenGL.

Карта нормалей состоит из трех каналов — RGB. Это нужно для переноса информации о трех осях XYZ из трехмерного пространства в двухмерное пространство текстуры.

Если tangent space normal адаптирует направление нормалей вершин объекта в зависимости от положения объекта в пространстве, то world space normal записывает статичную информацию. Грубо говоря, если объект при запекании был повернут лицевой стороной на север, а позже ты повернешь его на восток, нормали начнут отображаться некорректно.

И хоть невозможно двигать объект в пространстве, у таких карт есть одно преимущество — при работе с ними не нужно думать о направленности нормалей объекта.

Их часто используют в текстурировании, так как они могут дать вводную информацию о том, как свет падает на объект. В Substance painter практически каждый генератор работает в том числе и на основе информации из карты World Space Normal.

Object Space Normal — это модифицированная версия World Space Normal. Она отличается тем, что адаптирует карту нормалей и меняет ее ориентацию при перемещении объекта в пространстве.

Из недостатков: карта не подходит для использования на деформирующихся объектах. Например, её невозможно будет корректно применять на стену с симуляцией разрушения, или на развевающуюся на ветру ткань.

Изогнутые карты нормалей сочетают в себе информацию из AO и normal map. Они помогают усилить работу карты ambient occlusion и нужны для большего контроля над отражаемым от объекта светом. Удобно использовать, если нет возможности подключить Screen Space Reflection.

Большинство из перечисленных карт встречается в работе очень редко, но знать о них нужно, если планируешь расти в 3D. Чаще всего все используют Tangent Space Normal в качестве карты нормалей и World Space Normal для текстурирования.

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

Источник

Это норма — 3: типы карт нормалей

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

Карта нормалей касательного пространства (Tangent space normal map): самый распространённый сегодня тип карт нормалей; именно о нём мы говорили в предыдущих статьях. Он модифицирует направление нормалей модели на основании направления нормалей её вершин (то есть нам нужно контролировать нормали вершин lowpoly-модели).

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Карта нормалей касательного пространства Mikk (Mikk tangent space normal map). Не все 3D-редакторы вычисляют среднее нормалей вершин одинаково. Это приводит к тому, что в разных движках внешний вид карт нормалей отличается, поэтому нам нужно запекать карту нормалей при помощи того же способа, который использует программа рендеринга (это называется «использовать синхронизированный рабочий процесс (synched workflow)»)

Mikk предложил способ вычисления нормалей вершин, который должен был стать универсальным, чтобы все программы вычисляли их одинаково. С точки зрения рабочего процесса это означает, что можно использовать низкополигональную модель (lowpoly) со всеми её усреднёнными нормалями (с одной группой сглаживания (smoothing group) или со сглаживанием всех граней), запечь карту нормалей в касательном пространстве Mikk, и это будет выглядеть точно так же, как высокополигональная модель (highpoly), без необходимости устранения ошибок сглаживания или отделения жёстких граней в UV. В будущем я напишу туториал о том, как это делается.

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

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Двухканальная карта нормалей касательного пространства (2-channel tangent space normal map): оказывается, что при помощи информации, хранящейся в двух из трёх каналов карты нормалей, компьютер может вычислить третий, снизив занимаемый объём памяти ценой увеличения количества вычислений. Так как обычно в большем дефиците находится память, такая оптимизация используется часто и некоторые движки выполняют её автоматически (например, Unreal Engine, когда мы устанавливаем для сжатия нормалей текстуры параметр «normal map»). Освободив один канал карты нормалей, мы можем уменьшить размер текстуры или использовать этот канал для metalness/roughness/opacity…

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

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Карта нормалей мирового пространства (World space normal map): эта карта нормалей вместо того, чтобы модифицировать направление нормалей вершин, полностью их игнорирует и меняет способ отражения света lowpoly-моделью в мировом пространстве (world space) (при запекании она считает, что нормали вершин параллельны осям мира).

Можно сказать, что карта нормалей касательного пространства сообщает модели «ты должна отразить свет вправо», а карта нормалей мирового пространства — «ты должна отразить свет на восток».

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

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

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

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

Стоит также помнить, что мировые координаты в разных приложениях реализованы по-разному: в Unreal, 3D Studio Max, Blender вверх направлена ось Z, а в Maya, Modo и Cinema4D — ось Y. Это значит, что при переносе между приложениями карты нормалей мирового пространства могут портиться.

Карта нормалей пространства объекта (Object space normal map): это улучшенная версия предыдущего типа карт, и она очень на него похожа. Идея заключается в том, что при перемещении модели в мире её карта нормалей мирового пространства должна переориентироваться относительно объекта.

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

Наклонные карты нормалей (Bent normal maps): по сути, в них сочетается информация AO и карты нормалей, наклоняющая направления нормалей так, чтобы свет стремился отражаться к тем частям модели, на которые попадает свет.

Такие карты используются для улучшения Ambient Oclussion и чтобы избежать эффекта под названием «утечка света» (light leaking), при котором модель может отражать свет теми частями, которых он не может достичь. Лично я никогда ими не пользовался, но исследовал бы их возможности, если бы столкнулся с заметной «утечкой света». Более подробную информацию можно найти здесь, здесь и здесь.

16-битные карты нормалей (16 bit normal maps): иногда, когда на карте нормалей присутствует очень плавный градиент, мы можем замечать появление полос. Эти полосы возникают из-за нехватки цветов для представления плавного градиента, обычно вызванной сжатием текстур.

Узнать больше о 16-битных картах нормалей можно у самого бога туториалов — Earthquake.

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

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

Так какой же из типов мы должны использовать?

В 90% случаев наилучшим решением являются карты нормалей касательного пространства Mikk. В отличие от вариантов с использованием карт нормалей пространства мира или объекта, модель сможет деформироваться, а направление нормалей останется правильным.

Следует запекать карту нормалей в том же касательном пространстве, что и в программе рендеринга. Наиболее распространённое касательное пространство — это Mikk, так что по возможности используйте его.

Если же на вашей карте нормалей появляется пикселизация, подумайте над использованием 16-карт нормалей или одного из упомянутых выше решений.

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

Благодарю за прочтение, надеюсь, статья была вам полезна. Спасибо Shnya за комментарии и помощь.

Источник

Learn OpenGL. Урок 5.5 – Normal Mapping

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Normal Mapping

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

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Как видно, освещение совершенно не учитывает предполагаемые для этой поверхности детали рельефа: отсутствуют и все мелкие трещинки, и углубления с цементом неотличимы от остальной поверхности. Можно было бы использовать карту зеркального блеска дабы ограничить освещенность определенных деталей, которые находятся в углублениях поверхности. Но это больше похоже на грязный хак, чем на рабочее решение. Что нам нужно, так это способ обеспечить уравнения освещения данными о микрорельефе поверхности.
В контексте известных нам уравнений освещения подумайте вот над каким вопросом: при каких условиях поверхность будет освещена как идеально плоская? Ответ связан с нормалью к поверхности. С точки зрения алгоритма освещения информация о форме поверхности передается только через вектор нормали. Поскольку у представленной выше поверхности вектор нормали постоянен всюду, то и освещение выходит равномерным, соответствующим плоскости. А что если передавать алгоритму освещения не единственную нормаль, постоянную для всех фрагментов, принадлежащих объекту, а нормаль уникальную для каждого фрагмента? Таким образом вектор нормали будет слегка меняться на основе рельефа поверхности, что создаст более убедительную иллюзию сложности поверхности:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

За счет использования пофрагментно отличающихся нормалей алгоритм освещения будет считать поверхность состоящей из множества микроскопических плоскостей, перпендикулярных своему вектору нормали. В итоге это ощутимо добавит объекту фактурности. Техника применения нормалей уникальных для фрагмента, а не всей поверхности – это и есть Normal Mapping или Bump Mapping. В применении к уже знакомой сцене:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

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

Normal Mapping

Итак, получается, нам необходимо обеспечить алгоритм освещения нормалями, уникальными для каждого фрагмента. Воспользуемся уже знакомым по текстурам диффузного и зеркального отражения методом и используем обычную 2D текстуру для хранения данных о нормали в каждой точке поверхности. Не удивляйтесь, текстуры отлично подходят и для хранения векторов нормалей. Далее нам останется только осуществить выборку из текстуры, восстановить вектор нормали и провести расчеты освещения.

На первый взгляд может быть не очень ясно, как сохранить векторные данные в обычной текстуре, которая типично используется для хранения информации о цвете. Но задумайтесь на секунду: цветовая триада RGB по сути и есть трехмерный вектор. Похожим образом можно сохранить компоненты вектора нормали XYZ в соответствующих компонентах цвета. Величины компонент вектора нормали лежат в интервале [-1, 1] и потому требуют дополнительного преобразования в интервал [0, 1]:

Такое приведение вектора нормали в пространство цветовых компонент RGB позволит нам сохранить в текстуре вектора нормалей, полученные на основе реального рельефа моделируемого объекта и уникальные для каждого фрагмента. Пример такой текстуры – карты нормалей – для все той же кирпичной кладки:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Интересно отметить синий оттенок этой карты нормалей (практически все карты нормалей имеют схожий оттенок). Так получается, поскольку все нормали сориентированы приблизительно вдоль оси oZ, которая представляется координатной тройкой (0, 0, 1), т.е. в виде цветовой триады – чисто синий цвет. Небольшие изменения оттенка являются следствием отклонения нормалей от положительной полуоси oZ на некоторых участках, что соответствует неровностям рельефа. Так, можно заметить, что на верхних кромках каждого кирпича текстура приобретает зеленый оттенок. И это логично: на верхних гранях кирпича нормали должны бы быть сориентированы больше в сторону оси oY (0, 1, 0), что соответствует зеленому цвету.

Для тестовой сцены возьмем плоскость, сориентированную в сторону положительной полуоси oZ и используем для нее следующие диффузную карту и карту нормалей.

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Как видно, они не совместимы. И немного покумекав можно понять, что DirectX полагает касательное пространство леворуким, а OpenGL праворуким. Подсунув иксовую карту нормалей нашему приложению без изменений получим некорректное освещение, причем не всегда сразу видно, что оно некорректное. Самое заметное — то, что выпуклости в формате OpenGL становятся углублениями для DirectX и наоборот.
Что касается адресации: загружая данные из файла текстур в память мы предполагаем, что первый тексель — это левый верхний тексель изображения. Для представления текстурных данных в памяти приложения это, вобщем случае, верно. Но OpenGL использует другую систему текстурных координат: для нее первый тексель — это левый нижний. Для корректного текстурирования изображения, обычно, переворачиваются по оси Y еще в коде того или иного загрузчика файлов изображений. Для используемой в уроках либы Stb_image нужно добавить установку флажка

Что самое забавное, то корректно в плане освещения отображаются два варианта: карта нормалей в нотации OpenGL с включенным отражением по Y или карта нормалей в нотации DirectX с выключенным отражением по Y. Освещение в обоих случаях работает корректно, разница останется только в инверсии текстур по оси Y.

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

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

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

Теперь, если медленно менять положение источника света в сцене, то можно ощутить иллюзию рельефности поверхности, обеспечиваемую картой нормалей:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Но остается одна проблема, которая радикально сужает круг возможного применения карт нормалей. Как уже отмечено синий оттенок карты нормалей намекал на то, что все вектора в текстуре ориентированы в среднем вдоль положительной оси oZ. В нашей сцене это не создало проблем, ведь нормаль к поверхности плоскости также была сонаправлена с oZ. Однако, что случится, если мы изменим положение плоскости в сцене так, что нормаль к ней будет сонаправлена с положительной полуосью oY?

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Освещение оказалось полностью неверным! И причина проста: выборки нормалей из карты все также возвращают вектора, ориентированные вдоль положительной полуоси oZ, хотя в данном случае им следовало бы быть ориентированными в направлении положительной полуоси oY нормали поверхности. В данный же момент расчет освещения идет так, будто нормали к поверхности расположены так, будто плоскость все еще ориентирована в сторону положительной полуоси oZ, что дает неверный результат. Рисунок ниже более наглядно показывает ориентацию считанных из карты нормалей относительно поверхности:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

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

Есть другой, математически более сложный подход, предлагающий вести расчеты освещения в другой системе координат: такой, что вектора нормали в ней всегда примерно совпадают с положительной полуосью oZ. Другие вектора, требующиеся для расчетов освещения тогда преобразуются в эту систему координат. Такой метод дает возможность использовать одну карту нормалей для любой ориентации объекта. А эта специфичная система координат называется касательным пространством или tangent space.

Касательное пространство

Стоит отметить, что вектор нормали в карте нормалей выражен непосредственно в касательном пространстве, т.е. в такой системе координат, что нормаль всегда направлена примерно в направлении положительной полуоси oZ. Касательное пространство задано как система координат, локальная для плоскости треугольника и каждый вектор нормали задается в рамках этой системы координат. Можно представить эту систему и как локальную систему координат для карты нормалей: все вектора в ней заданы направленными в сторону положительной полуоси oZ вне зависимости от конечной ориентации поверхности. Используя специально подготовленные матрицы трансформации можно преобразовать вектора нормалей из этой локальной касательной системы координат в мировые или видовые координаты, ориентируя их в соответствии с окончательным положением поверхностей, подвергаемых текстурированию.
Рассмотрим предыдущий пример с некорректным применением normal mapping’а, где плоскость была сориентирована вдоль положительной полуоси oY. Так как карта нормалей задана в касательном пространстве, то один из вариантов корректировки – это расчет матрицы перехода нормалей из касательного пространства в такое, что они бы стали ориентированы по нормали к поверхности. Это привело бы к тому, что нормали стали бы выровнены вдоль положительной полуоси oY. Замечательным свойством касательного пространства является тот факт, что расчитав такую матрицу мы сможем переориентировать нормали к любой поверхности и её ориентации.

Такая матрица сокращенно обозначается как TBN, что есть сокращение от названия тройки векторов Tangent, Bitangent и Normal. Эти три вектора нам необходимо найти, дабы сформировать эту матрицу смены базиса. Такая матрица осуществляет переход вектора из касательного пространства в какое-либо другое и для её формирования необходимы три взаимоперпендикулярных вектора, ориентация которых соответствует ориентации плоскости карты нормалей. Это вектор направления вверх, вправо и вперед, набор знакомый нам по уроку о виртуальной камере.
С вектором верх все ясно сразу – это наш вектор нормали. Вектор вправо и вперед называются касательная (tangent) и бикасательная (bitangent) соответственно. Следующий рисунок дает представление об их взаимном расположении на плоскости:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Расчет касательной и бикасательной не настолько очевиден, как расчет вектора нормали. На рисунке можно заметить, что направление касательной и бикасательной карты нормали выровнены с осями, задающими текстурные координаты поверхности. Данный факт и положен в основу расчета этих двух векторов который потребует некоторой сноровки с математикой. Посмотрите на рисунок:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Преобразуя в поэлементную запись получим:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsвычисляется как вектор разности двух векторов, а Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsи Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsкак разности текстурных координат. Остается найти две неизвестных в двух уравнениях: касательную Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsи бикасательную Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps. Если еще припоминаете уроки алгебры, то знаете, что такие условия позволяют решить систему и для Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsи для Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps.
Последняя приведенная форма уравнений позволяет нам переписать её в форме матричного умножения:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Попробуйте мысленно провести матричное умножение, чтобы убедиться в верности записи. Запись системы в матричной форме позволяет гораздо легче понять подход к нахождению Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsи Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps. Умножим обе части уравнения на величину обратную Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Получаем решение относительно Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsи Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps, которое, однако, требует расчета обратной матрицы изменений текстурных координат. Не будем углубляться в подробности вычисления обратных матриц – выражение для обратной матрицы выглядит как произведение числа, обратного к детерминанту исходной матрицы, и присоединенной матрицы:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Данное выражение и есть формула для расчета вектора касательной Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsи бикасательной Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal mapsна основе координат граней треугольника и соответствующих текстурных координат.
Не переживайте, если суть приведенных математических выкладок ускользает от вас. Если вы понимаете, что касательную и бикасательную мы получаем на основе координат вершин треугольника и их текстурных координат (поскольку текстурные координаты также принадлежат касательному пространству) – это уже половина дела.

Расчет тангентов и битангентов

В примере этого урока мы взяли простую плоскость, смотрящую в сторону положительной полуоси oZ. Сейчас же попробуем реализовать normal mapping используя касательное пространство, чтобы иметь возможность ориентировать плоскость в примере как нам вздумается, не разрушая эффекта normal mapping’а. Используя вышеописанный расчет мы вручную найдем касательную и бикасательную к рассматриваемой поверхности.
Примем, что плоскость составлена из следующих вершин с текстурными координатами (два треугольника заданы векторами 1, 2, 3 и 1, 3, 4):

Сначала рассчитываем вектора, описывающие грани треугольника, а также дельты текстурных координат:

Имея на руках необходимые исходные данные мы можем приступить к расчету касательной и бикасательной прямо по формулам из предыдущего раздела:

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

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

Получившиеся вектора касательной и бикасательной должны иметь значения (1, 0, 0) и (0, 1, 0) соответственно. Что вкупе с вектором нормали (0, 0, 1) формируют ортогональную матрицу TBN. Если визуализировать полученный базис вместе с плоскостью, то получится следующее изображение:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Теперь, имея рассчитанные вектора можно приступать к полноценной реализации normal mapping’а.

Normal mapping в касательном пространстве

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

В самом коде вершинного шейдера сформируем непосредственно матрицу:

В приведенном коде сперва преобразуем все вектора базиса касательного пространства в систему координат, в которой нам удобно работать – в данном случае это мировая система координат и мы умножаем вектора на модельную матрицу model. Далее мы создаем саму матрицу TBN просто передавая конструктору типа mat3 все три соответствующих вектора. Обратите внимание на то, что для полной корректности порядка вычислений необходимо проводить умножение векторов не на модельную матрицу, а на матрицу нормалей, поскольку нас интересует лишь ориентация векторов, но не их смещение или масштабирование

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

Итак, получена матрица TBN, как нам ее использовать? По сути есть два подхода к её применению в normal mapping’е:

Передача матрицы TBN делается простейшим образом:

В коде фрагментного шейдера, соответственно, задаем входную переменную типа mat3:

Имея матрицу на руках можно уточнить код получения нормали выражением перевода из касательного в мировое пространство:

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

Давайте также рассмотрим и второй подход. Он потребует получения матрицы обратной TBN, а также переноса всех векторов, участвующих в расчете освещения, из мировой системы координат в ту, что соответствует векторам нормали, полученным из текстуры – касательную. В данном случае формирование матрицы TBN остается неизменным, но перед передачей во фрагментный шейдер мы должны получить обратную матрицу:

Обратите внимание на то, что применена функция transpose()вместо inverse(). Такая подстановка справедлива, поскольку для ортогональных матриц (где все оси представлены единичными взаимно перпендикулярными векторами) получение обратной матрицы дает результат идентичный транспонированию. И это весьма кстати, поскольку, в общем случае, вычисление обратной матрицы куда более вычислительно затратное дело по сравнению с транспонированием.

В коде фрагментного шейдера мы не будем преобразовывать вектор нормали, вместо этого преобразуем из мировой системы координат в касательную прочие важные вектора, а именно lightDir и viewDir. Это решение также приводит все элементы вычислений в единую систему координат, на этот раз – касательную.

Второй подход кажется более трудоемким и требует больше матричных умножений во фрагментном шейдере (что сильно влияет на производительность). Почему мы вообще взялись его разбирать?
Дело в том, что перевод векторов из мировых координат в касательные предоставляет дополнительное преимущество: фактически мы можем вынести весь код преобразований из фрагментного в вершинный шейдер! Такой подход является рабочим поскольку lightPos и viewPos не изменяются от фрагмента к фрагменту, а значение fs_in.FragPos мы также можем перевести в касательное пространство в вершинном шейдере, интерполированное значение на входе во фрагментный шейдер будет вполне корректным. Таким образом, для второго подхода нет никакой надобности переводить все эти вектора в касательное пространство в коде фрагментного шейдера, в то время как первый этого требует – ведь нормаль является уникальной для каждого фрагмента.

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

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

Действительно, внешне все выглядит как надо:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Сложные объекты

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

Assimp предоставляет весьма полезный флаг опций при загрузке моделей: aiProcess_CalcTangentSpace. При его передаче функции ReadFile()библиотека сама займется расчетом сглаженных касательных и бикасательных для каждой из загруженных вершин – процесс похожий на рассмотренный здесь.

После этого можно прямо получить доступ к рассчитанным касательным:

Также необходимо будет обновить код загрузки, чтобы он учитывал получение карт нормалей для текстурированных моделей. Формат Wavefront Object (.obj) экспортирует карты нормалей таким образом, что флаг Assimp aiTextureType_NORMAL не обеспечивает корректной загрузки этих карт, в то время как с флагом aiTextureType_HEIGHT все работает корректно. Поэтому лично я, обычно, загружаю карты нормалей следующим способом:

Безусловно, для других форматов описания модели и типов файлов этот подход может не подходить. Также отмечу, что выставление флага aiProcess_CalcTangentSpace не всегда срабатывает. Нам известно, что вычисление касательных основывается на текстурных координатах, однако, зачастую авторы моделей применяют различные ухищрения к текстурным координатам, что ломает расчет касательных. Так, нередко применяется зеркальное отражение текстурных координат для симметрично оттекстурированных моделей. Если не учитывать факт зеркальности, то расчет касательных будет неверен. Assimp не делает такого учета. Знакомая нам модель нанокостюма вот не подходит для демонстрации, поскольку также использует зеркалирование.

Но с корректно оттекстурированной моделью, использующей карты нормалей и зеркального отражения, тестовое приложение дает весьма неплохой результат:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Как видно, применение normal mapping’а дает ощутимый прирост детальности и при этом дешев в плане затрат производительности.

Не стоит забывать, что применение normal mapping’а может позволить повысить производительность для конкретной сцены. Без его использования достижение детальности модели возможно только через увеличение плотности полигональной сетки, меша. Но данная техника позволяет добиться визуально того же уровня детализации для низкополигональных мешей. Ниже можно увидеть сравнение этих двух подходов:

Что такое normal maps. Смотреть фото Что такое normal maps. Смотреть картинку Что такое normal maps. Картинка про Что такое normal maps. Фото Что такое normal maps

Уровень детализации на высокополигональной модели и на низкополигональной с применением normal mapping’а практически неотличим. Так что эта техника – отличный метод заместить высокополигональные модели в сцене упрощенными практически без потери в визуальном качестве.

Последнее замечание

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

В тех случаях, когда касательные рассчитываются для больших и сложных мешей, имеющих значительное количество вершин, принадлежащих нескольким треугольникам, касательные вектора, обычно, усредняются, чтобы получить гладкий и визуально приятный результат normal mapping’а. Однако, это создает проблему: после усреднения тройка векторов TBN может потерять взаимную перпендикулярность, что также значит потерю ортогональности для матрицы TBN. В общем случае результат normal mapping’а, полученный на основе неортогональной матрицы, лишь слегка некорректен, но все же мы можем улучшить его.

Для этого достаточно применить простой математический метод: процесс Грамма-Шмидта или ре-ортогонализация нашей тройки векторов TBN. В коде вершинного шейдера:

Эта, пусть и небольшая, поправка улучшает качество normal mapping’а в обмен на мизерные накладные расходы. Если вам интересны детали этой процедуры, то можете посмотреть последнюю часть видеоролика Normal Mapping Mathematics, ссылка на который дана ниже.

Источник

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

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