Normal Edge Decals - краевые/кромочные декали
В наше время эта техника появляется во множестве игр. Один из самых ранних примеров, который мы можем увидеть это игра Hitman Absolution, которая находилась в разработке ещё в 2009 году, поэтому:
«Я не изобретаю заново колесо и не пытаюсь продать его, я просто демонстрирую вам, как работает это колесо»
В недавнем прошлом такие слова, как отложенный рендеринг (дополнительную информацию об этом см. в конце руководства), рендеринг, конвейер отложенного шейдинга, буфер, трим-шиты и т. п. были терминами только для супер техно-монстров индустрии :).
В настоящее время мы живем во времена, когда много информации находится в том, что люди называют Интернетом, и из-за того, что люди в отрасли учатся и становятся все более и более технически грамотными по сравнению с художниками несколько лет назад, и, учитывая все вышесказанное, информацию в целом становится все проще получить и применить. В конце этого pdf-файла вы найдете все ссылки на источники, которые смогут помочь вам расширить понимание этой темы, а также найти всю информацию, разбросанную по разным источникам, представленной в этом руководстве.
Резюмируя вышесказанное, я просто аккуратно собираю понятную информацию, которая поможет вам понять тему, используя то, что уже присутствует в различных руководствах и статьях в Интернете.
В идеале, при этом я хочу, чтобы вы быстро овладели техническими моментами, которые требуются для работы, и смогли больше сосредоточиться на искусстве, а не на поиске решений или устранении проблем.
Использование Normal Edge Decals
Normal Edge Decals (краевые/кромочные декали) могут быть очень полезны когда вы хотите “сломать” жёсткость геометрических линий, формирующих объект. Их обычно применяют к архитектурным ассетам и пропсам, которые используют тайловые текстуры. Это позволяет вам оставить нетронутым тайловый материал, в то же время получая некоторые дополнительные детали, такие как царапины, незначительные повреждения или сколы.
Простой пример с использованием Normal Edge Decals и без них
Только геометрия
Геометрия с Normal Edge Decals
Если вы обратите внимание, вы найдете Normal Edge Decals почти во всех некст-ген играх, в которые играли, а также в золотой классике гейминга.
Некоторые примеры игр, которые используют данную технологию
Давайте посмотрим на самые очевидные
Планируйте свою работу заранее
В идеале вам нужно иметь достаточное количество вариаций, чтобы хватило на большинство тайловых материалов, которые вы собираетесь использовать на крупномасштабных объектах, таких как архитектурные меши: углы стен, лестницы, отделочные материалы. Эти примеры различаются в зависимости от того типа проекта, над которым вы работаете.
Отыщите подходящий референс и запланируйте то, какие декали вы хотите создать
В зависимости от типа проекта, над которым вы трудитесь, и количества деталей, которые вы хотите получить, у вас есть два разных подхода при планировании тримов.
Любитель производительности
Одна текстура, содержащая все распространенные типы материалов, такие как: штукатурка, бетон, металл, дерево
и т. д. со средним уровнем разрушения
Преимущество: более высокая производительность
Любитель детализации
Одна текстура с уровнями разрушения для каждого типа материала
Преимущество: большая вариативность
Золотая середина
Легкие повреждения
Одна текстура, содержащая все распространенные типы материалов с легким/мягким состоянием повреждений
Тяжёлые повреждения
Та же самая текстура, имеющая более высокую степень повреждения
С этой опцией у вас есть широкий спектр возможностей повреждения большинства обычных материалов, при этом вы можете быть уверены, что количество текстур осталось оптимальным с точки зрения дальнейшей оптимизации.
Примечание: Очевидно, что выбор материалов был сделан из учета их распространенности среди всех остальных.
Создание Normal Trim Sheet
Нам нужен такого плана Trim Sheet для дальнейшей работы
Разделить текстуру на 5 (или более) зон A, B, C, D, E и поместить карту нормалей в центр каждой зоны, оставляя достаточное количество места для плавного бленда.
Примечание: Тримы намеренно были размещены вертикально, ведь мы собираемся применять их в основном на вертикальных углах. При желании, вы можете разместить их горизонтально.
Мы создаем только один Normal Trim Sheet (либо два, в зависимости от того, сколько детализации вам нужно) только один на все ассеты. Не нужно создавать новый Normal Trim Sheet для каждого отдельного ассета. Вместо этого вы должны использовать тот же самый Normal Trim Sheet для всех ваших ассетов на игровом уровне.
Просто создайте несколько примитивных мешей и скульптите углы так, как вы этого хотите, и решайте, как будет выглядеть карта нормалей на mesh декали. Затем создайте низкополигональную версию этого угла. Убедитесь, что вы покрыли область каждой зоны низкополигональной моделью (Low Poly).
Существует несколько способов этого достичь, но способ через zBrush наиболее прост для понимания
Вариант А
Импортируйте свой mesh в zBrush и в разделе «Geometry» нажмите «Divide» несколько раз (5-6 раз), затем активируйте опцию SMT (Smooth) и нажмите еще несколько раз, чтобы вы могли немного сгладить края, что поможет в дальнейшем при лепке.
Вкладка Geometry в zBrush
Вариант В
Помимо этого, вы можете несколько раз разделить свой меш с отключенной опцией SMT (smooth), а затем в разделе «Deformation» вы можете побаловаться с деформатором Polish. Это позволит вам лучше контролировать сетку и получить сглаженность кромок.
Вкладки Geometry и Deformation в zBrush
Вот некоторые из кистей, которые я использовал для создания карты нормалей для этого урока. Есть бесконечные способы добиться того же самого в zBrush
Для достижения лучшего эффекта сварного шва я бы посоветовал вам сгладить угол, который вы собираетесь скульптить
Создание альфы сварного шва в Photoshop
Этот метод можно применить к другому софту, например Substance Designer.
- A. Создайте новый документ 256x1024 (72 ppi, Grayscale, 16 bit)
- B. Используя Gradient Layer, вы можете создать сферическую форму с гладким черным контуром. Чтобы это сделать выберите Gradient Layer - New Fill Layer - Gradient. В диалоговом окне Gradient Fill укажите тип Radial и выставьте значение Scale на уровне 18%. Затем нажмите на полоску градиента в верхней части окна что поможет открыть Gradient Editor. В Gradient Editor настройте так, чтобы они повторяли картинку B. При этом может быть лучше будет установить средне-серый фон (120-128), чтобы лучше увидеть темное кольцо вокруг круга.
- С. Удалите фон и растрируйте слой
- D. Продублируйте слои по вертикали, чтобы заполнить все изображение, как на изображении D. Чтобы быстро создать несколько копий радиального градиента, переместите его в верхнюю часть холста, затем переведите его в режим трансформации с помощью Ctrl + Alt + T и слегка сместите его на нужное вам расстояние (можно зажать Shift для сохранения центровки) Нажмите Enter. С этого момента при нажатии Ctrl + Shift + Alt + T будет автоматически создаваться копия с заданным смещением. Объедините все слои, затем нажмите Ctrl+A и в верхнем меню нажмите Image > Crop. На этом этапе перейдите в Filter > Other > Offset и установите горизонтальное значение на 0 и вертикальное смещение на половину размера (512 пикселей).
- Е. Если у вас получился шов, вы можете легко удалить его с помощью Clone Stamp Tool
- G. Теперь перейдите в Filter > Blur > Gaussian Blur и попытайтесь получить результат, который получился у меня.
- H. Создайте новый слой с градиентом и установите Blending mode на Multiply поверх всего.
- I. Последний шаг — уменьшить интенсивность карты на некоторый уровень
- J. Вы должны получить что-то наподобие моего примера. В зависимости от типа сварного шва вы можете больше деформировать его, а также добавить к нему больше вариаций
Low Poly. Низкополигональная геометрия и Bake.
- Требуется иметь один UV шелл на одну зону
- Нужно иметь группу сглаживания Soften Edges Наличие одинаковых групп сглаживания поможет нам использовать Mesh декали под тем углом, который нам требуется
- Каждый UV шел должен быть развернут таким образом, чтобы покрывалась вся зона
- Попытайтесь разместить UV шелы с привязкой к координатной сетке. Таким образом это облегчит работу с ней в дальнейшем. В целом, привязка элементов к сетке является хорошей практикой для того, чтобы все было красиво и аккуратно. Большинство программ для работы с UV поддерживает эту функцию
Далее необходимо запечь с HP объекта на LP объект. В результате у вас получится примерно как у меня на примере выше. При этом, к сожалению, некоторые швы по вертикальной оси нужно будет удалить (что является проблемой, потому что далее мы будем использовать эту текстуру в качестве тайловой)
Теперь пришло время поправить швы. Вы можете быстро сделать это в Photoshop или подобной программе.
В окне Offset выставите значение равное половине от вашей текстуры
Сейчас пришло время немного исправить нашу текстуру. Так как мы запекали 3D-модель на гладком меше, нам нужно немного выровнять область между различными угловыми вмятинами, чтобы при использовании Mesh декалей переход был более плавным и бесшовным.
Результат сразу после бейка и исправленный вариант, как раз тот, что нам нужен
Чтобы получить такой результат, откройте запеченную карту Normal Trim Sheet с помощью Photoshop (или другого подобного ПО) и создайте новый слой. Затем мягкой кистью сделайте несколько штрихов в промежутках между шелами. Используйте цвет для плоской Normal Map. HEX: 7E7DFD
Пример простой альфа-маски (Simple) и маски с более точным контуром (Complex)
Последнее, что нам нужно сделать, это создать простую альфа-маску, чтобы замаскировать часть нормали, которая нам не требуется (пример: Simple).
Вы также можете создать более сложную и точную альфа-маску, которая будет повторять край Normal демаджа (пример: Complex), если вас не устроит результат, который даёт простая альфа-маска (пример: Simple).
Оба варианта должны работать хорошо, но при этом маска с более точным контуром (пример: Complex) даст качественный результат, но в то же время, если она будет сделана криво, то это может привести к другим проблемам с которыми вы столкнётесь загрзузив ваши Mesh декали в игровой движок.
Мой совет — начать нужно с простого варианта (пример: Simple), и, если карта нормалей Mesh декалей будет плохо смешиваться, вы можете попробовать сделать более точную маску (пример: Complex). Альфа-маски можно создать с помощью инструмента «Brush» в Photoshop, а каналы карты нормалей могут помочь вам увидеть и доработать некоторые зоны.
Добавление детализации на asset с помощью Normal Edge Decal
Всё, что вам нужно создать, это простой угловой mesh, который я буду называть Trim Mesh. Грани должны быть немного отдалены от исходного меша, чтобы избежать визуальных проблем, связанных с Z-Fiting.
Ширина граней может варьироваться в зависимости от желаемого масштаба Mesh декали. UV-развертка трим-меша должна быть правильно размаплена в нужную вам зону по характеру демеджа. Mesh должен иметь группу сглаживания - Soften edge.
Теперь давайте посмотрим на более сложные варианты использования Mesh декалей
Пример сложного ассета, который использует технику с Mesh декалями для более высокой детализации
Mesh декали на основе ассетов
В некоторых случаях вы хотите иметь обычную кромочную декаль у основания объекта, чтобы получить визуально более плавный переход между вертикальной и горизонтальной поверхностями.
В моём конкретном примере мне нужны некоторые детали снизу бетонных стен, но я хочу оставить пол без изменений. Важно, чтобы вы оставили эти скрытые грани. Потому что они позволяют краю угла быть мягким, что необходимо для плавного стыка двух поверхностей. Кроме того, вы можете повернуть нормали вершин (Vertex Normal) на 45 градусов чтобы зафейкать стык и сделать его более мягким.
Пример использования Mesh декалей между стыком двух ассетов (Стены и пол) на углах 90°
Проблема
Как вы можете заметить, что при удалении нижнего полигона у Mesh декали, который заходит под стенку, оставшейся полигон сразу встает на Hard Edge и у вас получается конфликт между запеченной нормалкой (которая пеклась на Soft Edge) и текущей группой сглаживания (Hard Edge).
Решение
Первый способ
Сохраните скрытые полигоны даже в том случае, если их не видно
- Плюсы: Занимает мало времени
- Минусы: остаются лишние полигоны
Второй способ
Вы удаляете скрытый полигон, который заходит под стенку и поворачиваете на 45° нормали нижних вертексов к низу, тем самым фейкая группу сглаживания Soft Edges
- Плюсы: Одна грань
- Минусы: Занимает много времени
Используя UV-развертку для Mesh декалей, вы получите что-то вроде такого примера
Пример зон, в которых лежат UV шеллы с Mesh декалями
Вам требуется сместить некоторые UV шеллы, чтобы отобразить трим на другой части текстуры, что даст вам большее разнообразия.
Как видите, UV grid действительно помогает нам фиксировать шеллы в правильной зоне и следить за тем, чтобы Mesh декали правильно отображались на краях.
Кроме того, поскольку мы привязались к сетке в UV Editor (при использовании Maya), мы можем установить Offset Tool на 0,2 (в моём случае), и каждый раз, когда я буду нажимать стрелки на клавиатуре (под кнопкой delete) влево и вправо, я буду смещать выбранный UV шел на предыдущую или следующую зону в UV пространстве, это позволит нам быстро переложить UV шеллы и посмотреть как они работают в том или ином случае.
Данный функционал смещения присутствует не только в Maya
3Ds MAX
В 3Ds Max после открытия UV Editor есть два параметра: абсолютные значения и относительные значения, вы можете менять их, нажимая на нужную иконку. Я бы рекомендовал использовать Relative mode: и в моем случае я использую 0,2 или -0,2, чтобы переместить UV шел в следующую или предыдущую зону.
MODO
В Modo в UV Editor вы выбираете UV трима, который хотите переместить, выбираете инструмент Transform и в свойствах Transform у вас есть значения U и V. Вы можете сместить значения, добавив или вычтя 0,2 (в моем случае)
Blender
В Blender после открытия UV Editor нажмите «N», чтобы появилась правая панель со свойствами. Значения являются абсолютными (absolute), поэтому вам нужно добавить или вычесть желаемое смещение (offset) . В моем случае 50 ед. (50 units)
Houdini
В Houdini вы создаете UVedit (или когда делаете uv), открываете UV Editor (Space + 5) и выбираете UV, затем добавляете или вычитаете 0,2 (в моем случае) в свойствах преобразования (Transform Properties)
Способы, которые позволяют изменить масштаб деталей на декали
Прежде всего, мы должны взять во внимание одну важную вещь: нам нужно всегда уменьшать ту часть Mesh декали, которая станет прозрачной, на основе Альфа-маски, которую мы создали ранее. По двум причинам: во-первых, из-за количества прозрачной области, которую мы рендерим: меньше альфы — дешевле.
Вторая причина заключается в том, что, уменьшая ненужную область Mesh декали, мы уменьшаем размер Trim-меша, что, в свою очередь, уменьшает дистанцию прорисовки (Draw distance) , а это означает, что сетка обрезки рендериться только крупным планом. Ниже приведены некоторые из доступных вариантов, если вы хотите масштабировать детали, выбирайте решение с умом.
Первоначальная Mesh декаль
Вид Trim-меша после увеличения
Trim-меш с отмасштабированным UV. При этом необходимо слегка подубрать геометрию для уменьшения прозрачной области (выделена ораньжевым)
Так выглядит уменьшенный в масштабе Mesh + UV развертка
Mesh декали в Unreal Engine
В Unreal Engine создать материал для обычной декали очень легко. Просто импортируйте две созданные вами текстуры (Normal map и Alpha) в редактор материалов, соедините их, как показано на примере, и установите свойства материала. Затем примените материал на слот для Mesh декали.
Пример настроек материала для Mesh декали в Unreal Engine
Mesh декали работают только с источниками света, которые были настроены как динамические (Movable) или постоянный (Stationary)
Причина, по которой не работает статическое освещение, заключается в том, что карты нормалей используются для имитации освещения ударов и разрушений, заставляя лучи света отскакивать в разных направлениях от реальной геометрии. Если вы запекаете освещение (Static), вы запекаете свет в карту освещения (Light Map) на вашем меше, это означает, что у вас не будет отсока лучей в реальном времени, а это в свою очередь говорит о том что карта нормалей не будет работать должным образом так, как я объясняю в этом уроке.
Вот сравнение в Unreal Engine. Я также применил тайловый материал, чтобы лучше показать результат, который вы получите. Normal Edge Decal всё ещё работает, даже при условии, что поверхность полностью плоская.
Чистый Asset без Mesh декалей, только на тайловых материалах
Asset, на который добавлены Mesh декали. Обратите внимание какую детализацию и разнообразие получил тот же самый объект с применением этой техники
Normal Edge Decal при работе с Unity
С помощью этого руководства вы также получите шейдер, который необходимо использовать для получения функционала Deferred Normal Decal.
Автор шейдера: Dickie McCarthy
Shader для Unity
Shader "Decal/NormalDecal" { Properties { _AlphaTex("Alpha", 2D) = "white" {} _NormalTex ("Normal", 2D) = "bump" {} } SubShader { Name "DEFERRED" Tags { "LightMode" = "Deferred" "Queue" = "Geometry+10" } LOD 100 Pass { Offset -1, -1 zwrite off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; float4 tangent : TANGENT; }; struct v2f { float2 uv : TEXCOORD0; float4 tSpace0 : TEXCOORD1; float4 tSpace1 : TEXCOORD2; float4 tSpace2 : TEXCOORD3; float4 vertex : SV_POSITION; }; sampler2D _NormalTex; float4 _NormalTex_ST; sampler2D _AlphaTex; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _NormalTex); float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w; fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign; o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); return o; } void frag (v2f i, out half4 outGBuffer2 : SV_Target2) { half3 norm = UnpackNormal(tex2D(_NormalTex, i.uv)); clip(tex2D(_AlphaTex,i.uv).a - 0.5); fixed3 worldN; worldN.x = dot(i.tSpace0.xyz, norm); worldN.y = dot(i.tSpace1.xyz, norm); worldN.z = dot(i.tSpace2.xyz, norm); worldN = worldN * 0.5f + 0.5f; outGBuffer2 = float4( worldN, 0); } ENDCG } } }
У вас в проекте, если он хорошо организован, должна быть папка с названием «Shader». Создайте файл и скопируйте код шейдера в эту папку (код шейдера см. выше). или, если у вас нет папки с шейдерами, просто поместите его куда-нибудь внутри проекта.
Создав файл шейдера, создайте новый материал и примените к нему этот шейдер. Затем назначьте текстуру, которую вы создали ранее. (Normal map и альфа)
Чтобы увидеть Mesh декали, вам нужно настроить камеру или проект через Rendering Path и выбрать тип Deferred
Normal edge decals будут работать только, если освещение выбрано как Real-time или Mixed
Normal Edge Decals + Vertex Painting при работе в Unreal Engine
Ещё одна технология, которую вы можете использовать для улучшения Normal Edge Decal это смешивание материалов через Vertex Paint. Vertex Paint даёт нам четыре дополнительных слота по RGBA, которые вы можете использовать для смешивания четырёх материалов между собой через "Мастер материал" для улучшения детализации ваших ассетов. В примере я использую красный канал для маскирования декали. Я также добавил ноду, которую конвертировал в параметр для управления интернсивностью маски.
Пример сборки материала Mesh декали в Unreal Engine
Всё это хорошо, но за это приходится платить. Когда вы используете Vertex Paint, вы можете столкнуться с некоторыми проблемами в лодировании, поскольку этот рабочий процесс зависит от плотности вертексов на вашей модели, которые вы уменьшаете с помощью лодирования.
Вы можете добавить цвета к вашим вертексам на модели в Unreal Engine с помощью инструмента рисования в режиме Vertex Paint (shift+4), либо в вашем 3D редакторе, который вы используете для моделирования.
Использование смешивания (Blending)
С помощью этого способа вы можете использовать цвета вершин как режим смешивания двух разных Normal Edge Decals. Например, вмятины от мягкого бетона могут сочетаться с разрушенным бетоном.
В этом примере я накладываю две mesh декали в центральной части и стираю красный цвет с двух последних перекрывающихся ветексов
В этом случае у вас не должно быть значительных проблем с отображением лодирования, т.к. у вас есть два разных меша, состоящих из очень небольшого количества полигонов.
Использование маскирования (Masking)
В текущем примере я использую vertex color, для маскирования Normal Edge Decals. Это позволяет устранить тайлинг и добавить некоторую вариативность.
Как видно на примере выше, я добавил некоторое количество вертексов, чтобы иметь возможность большего контроля при использовании Vertex Paint
Слабой стороной этого метода, является переключение ассетов на пониженный LOD при рендере и отрисовки кадра. Если вы генерируете ЛОДы автоматически например через Unreal Engine, то он будет создавать ЛОДы по своему внутреннему алгоритму, который вы не сможете контролировать в ручную, что означает потерю плотности вашей сетки на ассете в рандомном порядке и этот метод даст вам соответсвующие артефакты.
Плюсы
- Добавление деталей недеструктивным способом
- Разбитие грубых и жестких краев меша
- Относительная простота создания
- Меньшее количество уникальных текстур на углах
- Легкая автоматизация процесса создания тримов
Минусы
- Дополнительный Draw Call на ассете
- Не работает со статичным освещением
- Различные трудности при ЛОДировании
- Невозможность получить корректный силуэт края
Понимайте то, что делаете
В очень упрощенном виде, показывающем только несколько пассов, мы можем видеть, что происходит в буфере каждый раз, когда ваш компьютер рендерит кадр с помощью отложенного шейдинга (Deferred Shading Pipeline).
Через шейдеры мы можем получить доступ ко всем этим слоям и переопределить или изменить свойства для каждого из них.
Когда мы создаем шейдер в Unreal Engine, мы выбираем Deferred Decal как «Material Domain». По сути, мы говорим шейдеру, чтобы он воздействовал на один или несколько ранее показанных пассов. Как мы выбираем, на какой пасс мы хотим повлиять? При выборе Deferred Decal вы активируете «Decal Blend Mode». Оттуда вы можете выбрать другой способ смешивания декали, в нашем случае у нас есть «Normal», Это означает, что он будет влиять только на нормаль объекта.
Если нам нужны некоторые цветовые вариации (например, декали сухой крови или следы от краски), вы можете выбрать «Stain», а если нужен весь материал, вы просто оставьте его в режиме «Translucent» (например, лучше для декали краски с резкими вариациями).
Всё имеет свою цену. Как видно из этой «блок-схемы», мы добавили дополнительный пасс, который будет использовать буферизацию через каждый кадр. В идеале это не имеет большого значения. Проблемы начинаются, когда вы накладываете много mesh декалей друг на друга, так что будьте осторожны и не переусердствуйте, всегда помните игры - это в первую очередь оптимизация, мы не делаем кино!
Подводя итог
Теперь, когда вы узнали, как работает эта технология, и насколько круты в применении Normal Edge Decals, попытайтесь поразмышлять о других способах этого использования рабочего процесса в своих моделях.
К примеру, представьте, что вы хотите добавить пятно с крошечной каплей на кафельный пол. Или вы хотите украсить вашу атмосферу несколькими царапинами на стене. Или даже добавить несколько следов на грязном полу.
Все эти примеры достижимы с помощью тех же инструментов, которые я показал вам в этом уроке. Но я хочу, чтобы вы напрягли свои извилины и смогли найти своё собственное решение, попутно освоив этот рабочий процесс.
Автор статьи: Leonardo Iezzi
Перевод: Андрианов Николай