поясняю разницу: BUMP, NORMAL, HEIGHT, DISPLACEMENT Mapping
Тут была тема аналогочная, почитав ее, чтоб народ не путался, я хотел разъяснить что такое бамп маппинг, но пока минут 10 писал, тему удалили вроде 🙂 мне обидно стало вот я новую и начал. На нее можно не отвечать, это я так для общего образования пишу, без подробностей.
:-> 8) 🙂 8-> 🙂 так! подведем итог. Если серьезно:
Чтобы задать все эти выпуклости и впуклости, надо где-то хранить о них информацию. Способы хранения информации о рельефе:
1. Карта высот (HeightMap). В большинстве случаев серая текстура. Ну тут все просто, чем выше точка тем светлее она на на карте высот.
2. Карта нормалей (NormalMap). Тут уже хитрее. Текстура (карта нормалей) содержит не высоту, а вектор нормали вооброжаемой поверхности в данной точке (нормаль это вектор перпендикулярный поверхности). То есть в случае, если мы хотим изобразить горку посередине нашего плоского, квадратного полигона, то на карте нормалей на левом склоне горки вектор нормали будет наклонен чуть налево, на правом склоне соответственно направо. Технически в текстуре вектор нормали представляется с помощью 3-х значений (цветов), но это уже мне лень расписывать. В отличии от HeightMap, текстура NormalMap содержит три цвета на точку, поэтому она сиреневая 🙂 а не grayscale.
При прорисовке (рендеринге) рельефного полиона движок игры (или 3D редактор), накладывает обычную текстуру с учетом рельефа, который берет из либо NormalMap, либо HeightMap. И мы видим что реально плоский польгон выглядит рельефным.
3. Существует более прогрессивный способ задания рельефа, так называемая Displacement Map (карта смещений). В принципе она тоже вся серая и выглядит почти как карта высот. Принципиальное отличие заключается происходит на этапе подготовки модели для вывода на экран. Если выводим таким способом наш квадратный полигон с горкой по середине, DirectX подменит плоский полигон наполигон с _реальной_ горкой посередине этого квадрата. То есть он сам автоматом добавит полигоны там где задана горка (а она задана в Displacement Map). Еще раз отмечу, что в отличии от Normal и Height, этот способ реально создает рельеф на заданном полигоне (искривляет полигон). Естественно он самый качественный и тормозной, кол-во полигонов-то увеличивается. И вообще на сегодняшний день практичнее использовать NormalMap.
.. вроде все. Могу запостить несколько картинок для большей понятливости, так сказать на пальцах показать. Но вообще-то в инете подробной инфы достаточно. Шоб до завтра заучили! 🙂 Хотя я вижу некоторые это более-менее уже знают и понимают.
Вот небольшой пример из 3DStudio Max7 Tutorials, одна пешка содержит полигонов в 10 раз меньше чем другая :), а разницы при рендеринге почти нет. Все из-за правильного применения NormalMap.
Загрузка реальных ландшафтов в Unity 3D
Введение
Тема генерации ландшафтов путем применения разнообразных хитроумных алгоритмов достаточно широко освещалась на хабре (раз, два, три и продолжать можно до бесконечности). Перечисленные примеры касаются случайной генерации некой абстрактной местности для повышения реализма в конечных игровых продуктах. А как быть, если требуется смоделировать некую реальную местность?
По этой теме тоже довольно много разного рода публикаций в сети. Однако, многие из них опираются на использование платных приложений или расширений для Unity. Существуют описания и «дешевых» методов, но основная масса их ориентирована на получение так называемых heightmap — черно-белых квадратных изображений местности, где градациями серого определяется относительных уровень высот в данной точке. Существует ряд способов генерации подобных карт высот с использованием например инструментария GDAL. И такой подход не лишен недостатков, связанных с достаточной громоздкостью процедуры создания карты высот и последующей привязкой к полученной местности. Поэтому, в данной статье будет изложен некий альтернативный подход и интересующиеся приглашаются под кат.
1. Добыча геоданных
Тут всё уже давно изобретено до нас, за что следует благодарить NASA, выполнивших в свое время программу SRTM (Shuttle Radar Topography Mission) по радиолокационному картонированию земной поверхности. Данные, полученные в ходе миссии находятся в открытом доступе вот здесь. Идем по этой ссылке и наблюдаем наш родной «шарик» поделенный на зоны.
Для демонстрации описываемой методики выберем район «крыши мира», гору Эверест. Для этого щелкаем по нужному куску карты и жмем кнопку «Download».
Распаковываем скачанный архив, и находим там среди прочего файл srtm_54_07.tif в формате GeoTIFF. GeoTIFF — открытый стандарт хранения картографической информации. Анализируя данный файл можно получить данные по высотам точек земной поверхности. Так как формат открытый, организовать непосредственную работу с ним, скажем из Unity будет несложно, но мы, пока, для упрощения, пойдем более коротким путем и воспользуемся маленькой но полезной программкой 3DEM. Это софтинка бесплатна и легко качается с официального сайта. Качаем её и открываем в ней добытый нами GeoTIFF района Эвереста. При открытии нас попросят выбрать формат геоданных, выбираем GeoTIFF:
После чего выбираем вышеупомянутый файл и видим такую картину:
Показанный район довольно велик. Прямоугольником по центру показан интересующий нас район горы Эверест. Чтобы вырезать нужный кусок жмем F8, выбираем интересующую нас область и жмем Enter. Нам предложат уточнить границы участка по широте и долготе.
Уточняем если нужно и нажав ОК получим интересующий нас район на экране:
Если надо, повторяем эту процедуру. В конце концов мы выберем нужный район, а затем идем в главное меню по пути File → Save Terrain Matrix. Нам предложат выбрать формат сохраняемых данных:
Выбираем бинарный формат float, так как с ним будет меньше возни. Выбираем далее путь и имя сохраняемых файлов. В качестве выхлопа мы получим два файла
Его нетрудно получить из pdf-документа, идущего вместе с 3DEM. Главная информация находится в *.hdr-файле и выглядит она так
Опишу самые важные для нашей задачи поля
3. Хранение данных о высотах в Unity
Класс Terrain в Unity имеет публичное поле terrainData, через которое можно получить доступ к следующим полям
4. Преобразование геоданных в карту высот
Нормировать высоты достаточно просто:
где level[i,j] — нормированная высота; h[i,j] — высота в точке (i,j); h_min, h_max — минимальная и максимальная высота на участке. Для приведения размера матрицы к выставленным требованиям нужна аппроксимация высоты в зависимости от координаты. Воспользуемся простейшей линейной аппроксимацией. Пусть высота есть функция координат точки на участке . Тогда, выберем базовую точку
, совпадающую с одним из узлом заданной координатной сетки и разложим эту функцию в ряд Тейлора
При кажущейся сложности, формула легко реализуется кодом на C#
Пользуясь этой функцией легко формируем матрицу для карты высот
5. Плагин для редактора Unity
Чтобы облегчить жизнь мной был написан небольшой плагин для редактора движка UnityGeoDataLoader, позволяющий решать поставленную задачу. Этот продукт и его исходный код распространяются по лицензии GNU GPL v2.0. По указанной ссылке можно получить и то и другое. Там же есть и инструкция по использованию данного инструмента.
Дальше с этим террейном делаем всё что душе угодно — текстурируем, применяем шейдеры, расставляем другие объекты. Это уж на ваше усмотрение.
Заключение
Покритикую сам себя. Нехорошо, при открытости стандарта GeoTIFF использовать сторонний инструмент для добычи геоданных. По-хорошему надо весь код поместить в плагин, добавить возможности выбора региона по координатам и много чего ещё. Но предела совершенству нет, главное, что задача загрузки в движок реального ландшафта имеет вполне приемлемое и простое решение.
Карты высот и параллакс
Из этой статьи вы узнаете о картах высот (height maps), также называемых картами параллакса (parallax maps).
Что такое карта высот?
Как обычно, когда я говорю «карта», то имеют в виду текстуру, содержащую информацию о внешнем виде 3D-объекта. Карта высот/параллакса — это карта, которую можно использовать для того, чтобы создать иллюзию того, что одни части объекта выступают сильнее, чем другие, то есть имеют бОльшую высоту.
По описанию это может показаться очень похожим на карту нормалей (normal map), благодаря которой 3D-объект кажется более рельефным, но действует она немного иначе. Карта нормалей использует освещение, чтобы объект казался более рельефным, чем на самом деле. Карта высот использует параллакс, чтобы сделать объект выше, чем на самом деле.
Параллакс
Замечали ли вы в детстве, что когда идёшь вечером, луна идёт за тобой? Объекты, мимо которых мы проходим — или движемся параллельно им, приближаются и удаляются, но луна всегда занимает в небе одно и то же место. Если вы, как и я, выросли рядом с горами, то могли также замечать, что они тоже не очень быстро двигаются, однако если уехать достаточно далеко, они всё-таки останутся позади. Чем дальше от нас предметы, тем медленнее они «движутся» при изменении угла взгляда на них (например, когда проезжаешь их на машине) и чем ближе объекты, тем быстрее они смещаются при смене вашей позиции и угла взгляда.
В таких двухмерных играх-сайдскроллерах, как Mario или Rayman, создатели использовали этот эффект. Они создали несколько слоёв фона, прокручивающихся с разной скоростью в зависимости от того, насколько близкими они должны казаться. Это просто иллюзия — разумеется, все спрайты плоские, но она придаёт сцене ощущение глубины!
Однако в 3D-графике мы тоже можем использовать это явление. Но вместо прокрутки здесь можно комкать или растягивать координаты текстур в зависимости от направления обзора, чтобы обмануть глаз и увидеть глубину! Именно этим данный эффект отличается от карты нормалей. Карта нормалей оставляет неизменными координаты текстур, но изменяет сторону, в которую по нашим ощущениям направлен объект. Карта высот сохраняет направление, но меняет координаты текстур, которые мы используем для всех остальных карт.
Если посмотреть на них по отдельности, то различия очевидны. Вы можете воссоздать изображения из статьи в собственном проекте, или просто читать её.
Если вы хотите создать собственный проект, то перейдите по адресу www.textures.com/download/pbr0419/137925 и скачайте файлы в папку своего проекта, например, в Assets/Textures/Acoustic Foam. (Не волнуйтесь, текстуры бесплатны!) Затем создайте материал и установите этот шахматный паттерн в слот основной текстуры, а потом задайте материал плоскости. У материала оставьте шейдер Standard shader.
Материал плоскости имеет только этот шахматный паттерн в качестве основной текстуры albedo и больше никаких других карт.
Здесь использован шахматный паттерн как основная текстура albedo и карта нормалей в виде акустического поролона (acoustic foam). Заметьте, что шахматный паттерн по-прежнему идеально ровный.
Здесь шахматный паттерн используется как основная текстура albedo, а acoustic foam — как карта высот.
Если приглядеться, то можно увидеть, что эффект неравномерный! Так получилось, потому что направление обзора этих двух частей неодинаково.
Эффект довольно интересен, но лучше всего он работает, если вы смотрите на плоскость почти перпендикулярно, и разваливается при взгляде на плоскость сбоку.
Итак, всё это очень здорово, но иллюзия может добиться только этого. Похоже, что лучше всего её использовать в небольших дозах на тех объектах, на которые игрок не сможет смотреть под такими углами.
А вот плоскость с шахматным паттерном в качестве текстуры albedo, картой нормалей acoustic foam и картой высот acoustic foam. Они отлично сочетаются! Ну ладно, хватит болтовни, давайте уже напишем шейдер, выполняющий эту задачу!
Подготовка
Откройте сцену в Unity. Добавьте плоскость, нажав правой клавишей мыши внутри иерархии и выбрав 3D Object > Plane.
Установите transform плоскости в 0, 0, 0 и оставьте на ней материал по умолчанию, она нужна будет, чтобы дать нам представление о масштабе. Добавьте таким же образом ещё одну или две фигуры. Я буду использовать сферу и куб. Расположите их, где угодно, на плоскости или над ней. Скачайте эти бесплатные текстуры в свой проект: https://www.textures.com/download/pbr0579/138828 (или используйте любой другой набор текстур с картами высот!), например в Assets/Textures/CrystalOre. В той же папке или в подпапке папки Materials создайте новый материал под названием Crystal Ore. Примените новый материал к двум фигурам. Нажмите правой клавишей мыши в Assets/Shaders/Standard и выберите Create > Shaders > Standard Surface Shader
Назовите новый файл шейдера BasicParallax, затем дважды щёлкните по нему, чтобы открыть его в Visual Studio. Измените первую строку на Shader «Xibanya/Standard/BasicParallax», затем сохраните его и вернитесь в Unity.
Назначьте шейдер BasicParallax материалу Crystal Ore. Теперь можно перетащить в слот текстуры карту albedo.
Создаём шейдер
Мы уже говорили о том, как использовать карту нормалей, metallic map и так далее, поэтому я буду предполагать, что вы уже знаете, как это делается. (Если нет, то прочитайте информацию по ссылкам и возвращайтесь!).
Перейдите к созданному мной базовому шейдеру, нажмите на кнопку Raw, скопируйте и вставьте шейдер в BasicParallax (но перед сохранением обязательно измените название сверху на Xibanya/Standard/BasicParallax!). Теперь можно перетащить карту нормалей и карту AO.
Я создала этот минималистичный шейдер для записи всех свойств, используемых стандартной моделью освещения (Standard lighting model), и больше в нём ничего нет, поэтому требуется дополнительная настройка, чтобы шейдер мог использовать roughness map. Добавьте эту строку в свойства (например, над gloss map)
Добавьте это под surface pragma
Затем измените часть, после которой распаковывается glossmap, на это:
(Если вы незнакомы с roughness map или ключевыми словами, то о них можно прочитать здесь!) Завершив с этим, сохранитесь и возвращайтесь в Unity. Теперь перетащите roughness map и переключите флаг Roughness на true.
Отлично! Наконец мы подготовили основу, настало время приступать к параллаксу!
Создание шейдера параллакса
Наверху, в разделе свойств добавьте следующие пять строк:
Мы сделаем параллакс функцией, которая активируется/отключается ключевым словом _PARALLAXMAP. Для правильно применения карты параллакса нам нужно использовать касательное направление обзора. Если мы пишем поверхностный шейдер, то если ключевое слово задано (то есть мы его включили), это будет направление обзора, получаемое от структуры Input. Если ключевое слово _PARALLAXMAP не задано, мы всё равно будем получать касательное направление обзора, если выполняем запись в o.Normal. Однако возможно, что мы не всегда будем это делать, поэтому об этом легко забыть и запутаться, поэтому лучше привыкнуть использовать его каждый раз, когда нам нужно распаковать карту параллакса! В pragma ключевого слова Roughness добавим следующую строку:
и добавим в структуру Input float3 viewDir.
Наконец, объявим в подшейдере текстуру карты параллакса и свойства силы параллакса.
Сохраним код и вернёмся в Unity, чтобы убедиться, что не сделали никаких опечаток или ошибок. Если всё правильно, то теперь мы можем перетащить текстуру CrystalOre_1k_height в слот карты параллакса материала. Не забудьте там же включить параллакс.
Разумеется, это пока ни к чему не приведёт, ведь мы не внесли никаких изменений в функцию поверхности! Мы используем карту параллакса для определения того, как сжимать или растягивать координаты текстуры, поэтому нам нужно обрабатывать всё связанное с параллаксом перед всем остальным. Добавим следующее в самое начало функции поверхности:
Мы распакуем текстуру и возьмём зелёный канал (большинство карт высот чёрно-белые, из-за чего все каналы одинаковы, поэтому нам достаточно использовать один), а затем передадим его, силу параллакса и касательное направление обзора (удобно вычисленное за нас магией поверхностного шейдера Unity) во встроенную функцию под названием ParallaxOffset. ParallaxOffset — это величина, определяющая сжатие или растягивание UV-координат в зависимости от направления обзора. Её можно найти в библиотеке UnityCG.cginc, включаемой в каждый поверхностный шейдер. ParallaxOffset возвращает значение float2, которое мы затем можем прибавить к координатам текстуры IN.uv_MainTex (которые также являются float2!), чтобы каждая распаковываемая после этого текстура распаковывалась со смещением. Если вам любопытно, то это выглядит так, но вам необязательно знать, как это работает, чтобы добавить параллакс к своим поверхностным шейдерам!
(не добавляйте это в свой шейдер, этот код уже встроен!) И наша работа здесь на этом закончена! Сохранитесь и вернитесь в Unity. Поиграйтесь с ползунком Parallax Strength, чтобы увидеть эффект в действии.
В свойствах я при помощи ползунка с интервалом ограничил силу параллакса в пределах от 0 до 0.1, потому что при значениях выше 0.1 всё начинает выглядеть довольно безумно даже при самых идеальных углах обзора, но вы можете изменить свойство с интервала на float, чтобы поэкспериментировать с различной силой параллакса.
Разница между фальшивыми и истинными смещениями в 3D-графике
Bump maps (рельефные текстуры), Normal maps (карты нормалей), Displacement и Vector Displacement — вероятно, вы уже сталкивались хотя бы с одним из этих терминов. Несмотря на то, что о них уже есть много информации, похоже, многие путают их различия и последствия использования разных типов карт. В статье я расскажу о том, какие проблемы могут вызывать эти карты.
Все четыре типа текстур имеют одинаковое предназначение — они позволяют добавить на поверхность модели дополнительные детали, используя для этого разные способы. Эти способы можно разделить на две категории, которые я буду называть истинными смещениями (True Displacements) и фальшивыми смещениями (Fake Displacements). Истинные смещения перемещают вершины, а фальшивые стремятся достичь того же внешнего вида без изменения геометрии. Пока я сосредоточусь только на различиях между двумя категориями, а не буду анализировать каждую карту по отдельности.
В общем случае, истинные смещения обеспечивают более чёткие результаты, но сильно увеличивают время рендеринга.
Примечание на случай, если вы задаётесь вопросом, почему не упомянуты карты высот. Термин «карта высот» (Height map) описывает способ хранения информации, а не применения её к мешу. Карты высот могут применяться и как Bump, и как Displacement. В таких пакетах, как Substance используется этот термин, потому что в них карту высот можно использовать и как истинное, и как фальшивое смещение.
Прежде чем двигаться дальше, нужно упомянуть, что я VFX-художник, поэтому буду рассматривать тему с точки зрения VFX с использованием рендеринга с трассировкой пути (path tracing). Если вы используете другой способ рендеринга (например, игровые движки), то результаты будут отличаться. Возможно, в вашем движке даже имеется полная поддержка истинных смещений.
Чтобы понять, как работают фальшивые смещения, нам сначала нужно вкратце рассказать о трассировке пути. Лучи света испускаются из всех источников освещения сцены и отражаются от поверхностей объектов, пока не достигнут камеры. Есть и другой подход: лучи могут испускаться из камеры и отражаться, пока не достигнут источника света. Используемый способ не влияет на те эффекты, которые я покажу.
Угол отражённого луча вычисляется сравнением угла падающего луча к углу нормали поверхности. Те из вас, кто проходил векторную математику и не забыл её, может узнать слово «нормаль». В векторной математике, которая является фундаментом рендеринга, нормаль — это вектор, перпендикулярный к плоскости. Если упростить, то можно сказать, что каждая грань модели является плоской, то есть у каждой грани есть одна нормаль.
Примечание: на самом деле, полигоны не всегда являются плоскими. Чтобы обойти эту проблему, движки рендеринга разбивают все полигоны, в том числе и четырёхугольники, на треугольники, а затем вычисляют среднюю нормаль для всех треугольников, из которых состоит грань.
Карты нормалей называются так, потому что позволяют нам попиксельно хранить любые нормали поверхностей. Это означает, что мы можем свободно манипулировать направлением отражения лучей света, не изменяя при этом геометрию. Рельефные текстуры (Bump maps) преобразуют информацию о высотах в нормали поверхности во время рендеринга. Это означает, что для лучей света, которые, по сути, являются «глазами» движков рендеринга, нормали и Bump maps выглядят одинаково.
Слева направо: низкополигональная модель, истинное смещение, фальшивое смещение
Мы можем имитировать результаты истинного смещения, сопоставив угол нормали поверхности. В таком простом примере это может выглядеть удовлетворительно, но отсутствие деформации геометрии приводит ко всевозможным артефактам. Неважно, какой подтип текстур вы используете — Bump или Normal, Displacement или Vector Displacement, а также способ изготовления текстур — запекание или создание, артефакты зависят только от категории, потому что все они являются результатом того, что фальшивые смещения не деформируют геометрию, а истинные — деформируют.
Воздействие на освещение
Первым, что вы заметите при изучении примеров — отсутствие теней. Истинное смещение не только влияет на форму теней, отбрасываемых базовым мешем, но и создаёт новые формы, которые отбрасывают совершенно новые тени. Часто это наиболее заметно в случае самозатенения объектов, но случается и при отбрасывании теней на другие объекты.
Смещение геометрии модели приводит к самозатенению, потому что луч света не может упасть на ту же точку поверхности. Если источником света на этой схеме является солнце (параллельные лучи света), то при использовании истинного смещения создастся тень, отбрасываемая на всю выделенную красным область, чего не будет при фальшивом смещении.
Взглянув на это простой рендер, можно увидеть, что общее направление освещения передаётся обоими способами, но при фальшивом смещении истинные тени геометрии отсутствуют.
Отличным примером этого является создание кирпичной стены из плоской базовой геометрии. При истинном смещении тени в щелях стены обеспечивают ощущение глубины, а из-за отсутствия этих теней версия с фальшивым смещением выглядит очень плоской.
Но нужно сказать что отсутствие теней — не единственная видимая разница во взаимодействии со светом. При неравномерном истинном смещении мы увеличиваем площадь поверхности объекта, что приводит к повышению количества отражённого света. Поэтому при использовании фальшивого смещения тёмные области выглядят неестественно чёрными.
На рендере с небольшой пирамидкой, демонстрирующем отбрасывание теней. я увеличил контраст отрендеренного, чтобы маскировать этот эффект; так нам проще будет фокусироваться на отдельных аспектах. При взгляде на рендер без редактирования становится заметной нехватка отражённого света.
Кроме отсутствия отбрасываемых теней и недостатка отражённого света, к воздействию на освещение относится ещё один эффект. Он связан с тем, как геометрия принимает тени.
Как и в одном из предыдущих примеров, красным обозначены тени. При сравнении высоты теней, отбрасываемых на наш объект сферой, становится понятно, что на форму тени будет влиять только истинное смещение.
Истинное и фальшивое смещение, применённое к плоскостям, представляет собой волну, движущуюся вверх-вниз. Деформируется только тень, отбрасываемая на плоскость с истинным смещением, что усиливает ощущение глубины.
На все вышеупомянутые эффекты влияет угол падающего света относительно угла камеры. Если камера параллельна источнику освещения, то все эффекты как будто пропадают. Например, деформация теней тоже снижается, которому что та же деформация происходит и из вида камеры.
Кроме того, всё больше тени исчезает за самой геометрией.
Хоть это и сработает, такой подход не является решением. Тени и создаваемые или усиливаемые ими формы значительно повышают интересность сцены. И если вы используете несколько источников освещения, то всё равно сможете установить камеру параллельно только одному из них. Поэтому не позволяйте этим эффектам влиять на освещение в сцене или расположение камеры.
Глядя на последний рендер, вы могли заметить кое-что ещё. Хоть карта нормалей и воспроизводит те же значения яркости, пирамида всё равно выглядит очень плоской. Это вызвано эффектом, который я опишу ниже.
Параллакс
Являясь одним из основных принципов перспективы, параллакс описывает эффект, заставляющий объекты визуально двигаться относительно друг друга при движении камеры. Но это касается не только отдельных объектов, но и любых двух точек в 3D-пространстве. Это означает, что деформирование меша при помощи истинного смещения имеет влияние на параллакс.
Красными линиями я показал области, находящиеся у всех трёх объектах на одинаковой глубине, чтобы они могли служить отправной точкой. Синие линии сдвинуты вниз смещением. При взгляде сверху вниз истинное и фальшивое смещения выглядят почти одинаковыми, однако под углами падения линии на низкополигональной версии и версии с фальшивым смещением (Lowpoly и Fake Displacement) сохраняют равное расстояние, а на меше с использованием истинного смещения (True Displacement) они визуально движутся. Если мы наклоним камеру чуть дальше, то синяя линия на дальней части плоскости полностью исчезнет за центральной линией. При сдвиге синих линий вверх эффект будет обратным — передняя синяя линия почти полностью закроет центральную красную.
Некоторые игровые движки позволяют создавать фальшивый параллакс, называемый Parallax-mapping, при котором 2D-искажение применяется к отрендеренным пикселям, а не к геометрии. Это повышает точность, но влияет на производительность.
Забавный факт: некоторые художники используют параллакс очень интересными способами. Великолепным примером этого является Патрик Хьюз, в видео показана одна из его работ.
Углы в 90 градусов
Хотя при помощи истинного смещения можно создавать вертикальные смещения под 90 градусов, такого нельзя сказать о фальшивом смещении. Теоретически вертикальные углы можно хранить в картах нормалей, но это не имеет смысла, потому что у них не будет соответствующей области на низкополигональном меше.
На показанном выше изображении зелёной линией обозначена поверхность базового меша, а красной — высокополигональная поверхность, которую мы запечём в меш. Градиент, возникший на низкополигональной модели, демонстрирует значения, которые будет иметь получившаяся карта нормалей. Каждый угол высокополигональной поверхности может быть сопоставлен с областью низкополигональной модели, за исключением вертикального угла между областями 1 и 2, потому что он не имеет никакой ширины относительно базового меша. Рельефные текстуры (Bump maps) имеют ту же проблему, потому что во время рендеринга они преобразуются в нормали поверхностей. На первом изображении ниже показан профиль высокополигональной поверхности, которая используется для запекания нормалей и смещения, а второе изображение — это рендер с использованием запечённых текстур.
Как видите, все остальные крутые углы всё равно можно сохранить в карту нормалей, хоть они и представлены небольшими областями, но углы в 90 градусов совершенно пропадают. Обратите внимание, что обычно стоит избегать любых крутых углов с тестурами, даже при использовании истинного смещения. Такие виды смещения растягивают пиксели других текстур.
Силуэт
То, что фальшивое смещение не меняет форму геометрии, можно наглядно увидеть при изучении силуэта. В крайних случаях то же самое может даже происходить со внутренними наложениями, например, с носом, закрывающим часть щеки персонажа.
Обычно этот эффект заметен в двух случаях. Силуэты, которые должны быть плавными, оказываются резкими, а силуэты, которые должны иметь множество высокочастотных деталей, внезапно теряют эти детали.
Подповерхностное рассеяние
Если в создаваемом вами графическом ассете используется Sub Surface Scattering (SSS), то вы сможете наблюдать ещё один недостаток фальшивого смещения.
Вычисления SSS рандомизируют углы лучей света при их перемещении внутри объектов. Это значит, что они гораздо меньше зависят от углов поверхностей, чем от толщины и самой формы меша. Единственная причина, по которой мы видим в нашем примере эффект при использовании фальшивого освещения, заключается в том, что единственный свет, который достигает камеры из тёмных областей — это рассеянные лучи, а яркие области — это смешение всех лучей. Это создаёт в тёмных областях красный оттенок, но чёткость картинки не идёт ни в какое сравнение.
Чёрные области или растянутые отражения
Кроме неестественно чёрных областей, вызванных нехваткой отражённого освещения, есть ещё один эффект, вызывающий подобные артефакты. При использовании фальшивого смещения определённые сочетания нормали поверхности и угла луча могут привести к тому, что отражённый луч пройдёт через поверхность самого объекта.
Это не имеет никакого смысла, ведь мы не рендерим прозрачную поверхность. Чтобы решить эту проблему, в рендерерах придумали множество способов выхода из этой ситуации. Используемый способ зависит от движка рендеринга. Вот возможные варианты:
Другие рендереры, например Blender Cycles, перенаправляют лучи параллельно поверхности низкополигональной модели, что приводит к созданию ближайшего возможного луча. Хоть это и предотвращает их поглощение, при этом многие пиксели рядом друг с другом получают один выходной вектор, что зритель воспринимает как растянутые отражения.
Хоть я и не сталкивался с рендерерами, в которых применяется третий вариант, мне известен случай, в котором используется тот же принцип. Применение Soft Edges/Smooth Normals (разные названия одного понятия) к мешу интерполирует нормали поверхностей для имитации более плавной поверхности меша.
Обычно рендереры взаимодействуют с Smooth Normals так же, как и с фальшивым смещением. Если применить Smooth Normals к кубу, то резкие углы в сочетании с нормалями поверхностей приведут к той же дилемме, при которой рендерерам приходится выбирать один из трёх вариантов. Не знаю почему, но Arnold работает со Smooth иначе, чем с фальшивым смещением. Вместо уничтожения лучей он игнорирует Smooth Normals в тех местах, где луч должен пройти сквозь объект.
Хоть все три решения выглядят в моих примерах довольно некрасиво, проблема не так страшна, как кажется. Я использовал для этих рендеров очень яркие текстуры и, как всегда, чем ярче текстуры, тем заметнее становятся недостатки. Обычно вы не будете сталкиваться с таким сильным эффектом при использовании истинного или фальшивого смещения. Можно увидеть, насколько яркие мои текстуры, если взглянуть на сцену под углом.
Кроме того, эту проблему маскирует ещё один фактор: рендеринг является более сложным процессом, чем просто точно отзеркаленные отражения. Если вы рендерите блестящий хром, то да, вам скорее всего стоит быть внимательными, но если вы добавляете шероховатость зеркального отражения (Specular Roughness) или диэлектрические материалы (неметаллы), то этот эффект станет не таким выраженным.
Specular Roughness предназначена для имитации несовершенств поверхности на микроскопическом уровне; она реализуется добавлением случайного смещения к углу отражения. Чем шероховатей поверхность, тем больше интервал возможного смещения.
Рандомизация углов лучей размывает отражение, из-за неё часть лучей/сэмплов получает недопустимые углы. Само по себе это не позволит избавиться от проблемы полностью, вы всё равно будете видеть разницу в правильности отражения, но она будет менее очевидной.
Диэлектрические материалы отражают бОльшую часть падающего на них света под совершенно случайным углом, это называется рассеянным отражением (Diffuse Reflection), и только очень малая доля лучей отражается как зеркальное отражение (Specular Reflection). Это означает, что даже если поверхность совершенно глянцевая, проблема едва будет заметной.
Эти изображения отрендерены в Arnold; если изолировать Specular Reflection, мы всё равно можем видеть чёрные области, но они не особо заметны на финальном рендере.
Тесселяция/подразделение
Все описанные выше артефакты касались фальшивого смещения, но этот недостаток проявляется при использовании истинного смещения. Само по себе истинное смещение может создавать/воссоздавать только ту величину детализации, которую поддерживают полигоны. Это значит, что сначала нам нужно тесселировать/подразделить меш. Если не подразделять их достаточно мелко, то у нас всё равно может получиться геометрия, не поддерживающая все мелкие детали, хранящиеся в текстуре. Это означает, что может потребоваться сильное подразделение (subdivision) модели, из-за чего сцена станет очень «тяжёлой». К счастью, современные движки рендеринга имеют функцию автоматического добавления детализации, которая не может поддерживаться геометрией как фальшивое смещение. В некоторых рендерерах эта функция по умолчанию отключена, поэтому проверьте её. К сожалению, пока для неё не сложилось стандартного названия. В Arnold, например, она называется Autobump, а в Cycles — Displacement + Bump.
Чтобы понять смысл этой функции, взгляните на показанное ниже сравнение. Оба этих меша подразделены три раза, но все детали можно обеспечить только способом комбинирования.
Увы, но эта функция имеет свои баги, и многие аспекты могут привести к её неправильной работе, например, отсутствие фиксации масштаба/применения масштаба к объекту. Кроме того, может вызывать сложности использование Autobump с Vector Displacement.
Советую вам проверять правильность работы функции созданием сравнительных рендеров, особенно если вы начинающий. Один рендер сделайте с Autobump в сочетании с нужным количеством подразделений, другой без Autobump, но с очень высоким количеством подразделений, чтобы убедиться, что результаты совпадают.
Учтите, что в некоторых рендерерах использование Autobump вместе с шейдерами SSS нужно включать отдельно. Проблемы использования фальшивых смещений всё равно будут возникать для деталей, добавляемых функцией Autobump, хоть они и не окажутся особо сильными для очень мелких деталей, например, пор кожи.
Заключение
И истинные, и фальшивые смещения — отличные способы повышения качества моделей. Я намеренно использовал очень сильные примеры, чтобы чётче продемонстрировать все артефакты. Пусть это не вводит вас в заблуждение о том, что фальшивое смещение, например карты нормалей, не нужно использовать никогда.
Основное правило заключается в том, что чем весомей будет текстура влиять на модель, тем сильнее окажутся артефакты. Поэтому какой бы способ вы не использовали, всегда пытайтесь передать все основные формы через базовую топологию. Это практически необходимо при использовании фальшивого смещения, но также важно и при истинном смещении. Если вы будете соблюдать это простое правило, то сможете получать практически одинаковые результаты при обоих способах. Удастся ли вам определить, в каком случае используется истинное, а в каком фальшивое смещения?
Как и в любом сложном деле, выбор зависит от требований и баланса между качеством и производительностью. Если вы работаете с фоновыми ассетами, то, возможно, не стоит увеличивать время рендеринга использованием истинного смещения, особенное если в сцене много ассетов.
С другой стороны, если вы работаете над ассетом героя, то лучше всего использовать истинное смещение, потому что оно обеспечивает более чёткие результаты. Даже на последнем показанном рендере два способа всё равно имеют различия в качестве.
Однако у этого правила существуют исключения. Например, если график работы над видеорядом чрезвычайно плотный, то использование фальшивого смещения вместо истинного поможет вам ускорить рендеринг. А поскольку вы рендерите последовательность кадров, сокращение времени рендеринга будет умножаться с каждым дополнительным кадром.
Или, допустим, вам нужен конкретный материал, и все хорошие текстуры, которые вы находите в Интернете, имеют только карты нормалей, а у вас нет времени на самостоятельное создание материала. В таком случае вам, скорее всего, стоит использовать карту нормалей, даже если вы работаете над ассетом героя. Такое случается со многими отсканированными материалами, потому что проще и легче захватить высококачественные карты нормалей, чем создавать высококачественные смещения. Если вам интересно, как это делается, то стоит прочитать следующую статью. (Хотя я и не рекомендую использовать для выполнения таких операций смартфон.)
Даже если вы работаете со сложной 3D-фигурой, например, с лицом человка, то похожие техники можно использовать для создания высококачественных карт нормалей.




































