Имитируя объём: как карты нормалей помогают заменить высокополигональные объекты
Что такое карты нормалей, и как происходит их запекание для низкополигональных моделей.
3D-художник Карлос Лемос опубликовал на сайте 80 LEVEL туториал, в котором подробно рассказал о принципах, на основе которых работают карты нормалей, а также поэтапно описал процесс запекания. А мы выбрали из него ключевую информацию, которая поможет новичкам разобраться в этой теме.
Как работают карты нормалей
Чтобы понятнее объяснить принципы работы карт нормалей, Лемос обратился к истории 3D-моделирования. Первые 3D-модели выглядели примерно так.
Первое очевидное решение этой проблемы состояло в увеличении количества полигонов — это сделало поверхность более ровной и гладкой.
Но для визуальной гладкости объекта требовалось огромное количество полигонов, что негативно сказывалось на производительности. Поэтому нужно было иное решение. Им как раз и стали карты нормалей.
Принцип работы нормалей проще всего показывать на наглядном примере. Если провести от центра полигона линию, которая будет перпендикулярна его поверхности, то это и будет нормаль. Её цель состоит в том, чтобы контролировать направление поверхности. Когда свет падает на поверхность, используется именно эта нормаль, чтобы правильно рассчитать отражение.
Иными словами, отражение света будет симметричным относительно нормали полигона. Именно так работают отражения в реальном мире.
По умолчанию все полигоны отражают световые лучи перпендикулярно своей поверхности (как в реальности), потому что нормали полигона по умолчанию перпендикулярны поверхности полигона.
Благодаря этому поверхность воспринимается гладкой — результат можно сравнить с моделью, состоящей из огромного количества полигонов. Именно по этому принципу работают группы сглаживания в 3ds Max, Blender и устанавливается рёбра как hard или smooth в Modo, Maya.
Чтобы не получалось таких странных объектов, существует угол сглаживания — если угол, под которым соединяются полигоны, выше угла сглаживания, то переход будет мягким, если ниже, то жёстким.
Тем не менее нормали полигонов используются скорее для нанесения текстур, искривляющих отражение света, а не для сглаживания переходов между полигонами. Для этого в первую очередь используются нормали вершин (вертексные нормали). В основе этого подхода лежит примерно та же идея, но немного более сложная.
Каждая вершина может иметь одну или несколько связанных нормалей. Если у неё есть одна нормаль, то она называется усреднённой нормалью вершины (averaged vertex normal), а если несколько, то разделённой (split vertex normal).
Допустим, есть два полигона, соединённых ребром. Если переход между двумя гранями гладкий, то каждая вершина имеет одну нормаль с усреднённым значением нормалей полигонов.
Если переход жёсткий, то каждая вершина имеет несколько нормалей — так появляется пробел, который визуально разделяет две плоскости. Это и называется разделённой нормалью вершины.
Чтобы воссоздать отражающие свойства высокополигональной модели на низкополигональной модели, как раз и применяются карты нормалей — она запекается в виде текстуры и накладываются на нужный объект. Вся информация о том, как модель должна отражать свет, хранится в текстуре. Это и называется картой нормалей.
Запекание карты нормалей
Чтобы объяснить принцип запекания карты нормалей, начнём с примера.
Нормали нельзя просто взять и перенести на другой объект, потому что на лоуполи-модели нет нужных полигонов. Чтобы нормали на лоуполи правильно имитировали затенение, им нужно придать такое же направление, как и на хайполи.
Движок использует текстуру для «модификации» низкополигональных моделей, что позволяет им отражать свет так же, как высокополигональным. Но это всего лишь текстура, поэтому она не может повлиять на реальную форму и силуэт объекта.
Стоит помнить, что карты нормалей — это не обычные текстуры: они содержат информацию о нормалях, а не о цвете. Но карту нормалей можно представлять как набор из трёх текстур, содержащихся в одном изображении.
В заключение пройдёмся по ключевым вещам, которые описаны в тексте. Нормали — это векторы, которые используются для определения того, как свет отражается от поверхности. Они могут применяться для управления переходом между гранями: через усреднение нормалей связанных вершин, чтобы сделать плавный переход, или разделение, чтобы сделать жёсткий переход.
Также нормали можно применять для создания низкополигональной модели, которая сможет отражать свет так же, как высокополигональная модель. Эта информация хранится в трёх отдельных каналах изображения, и 3D-редактор считывает её, чтобы понять, в каком направлении должен падать свет.