Создание шейдеров или материалов является одной из самых интересных и ответственных стадий разработки визуала в сцене.
Условно материалы можно разделить на несколько категорий по их назначению.
Например, ландшафтные материалы, включающие в себя несколько слоев, материалы с особыми свойствами D-buffer для декалей, материалы для растительности, а также материалы для визуальных эффектов, работающие в связке с системой частиц Niagara.
Такие материалы отличаются режимами исполняющей ноды или набором различных элементов и функций, которые вы добавляете на граф разработки и связываете в единую логику.
Я полагаю, что если вы плохо ориентируетесь в этой теме, то разбираться с такими классами рановато, вместо этого лучше начать с изучения основных узлов, формирующих сколь угодно сложную логику.
А уже после переходить к специфике назначения того или иного шейдера.
Предлагаю рассмотреть основные узлы, которые активно используются при создании логики материала:
1. Результирующий узел
Сюда выводятся все параметры, т.н. атрибуты, отвечающие за разные аспекты будущего материала:
Базовый цвет, оптические свойства, типа бликов или шероховатости, контактные тени, формирующие микродетализацию наряду нормалями, свойства металличности и прочее…
2. Текстурный объект
Узел, позволяющий внедрять в логику материала текстуру.
3.Текстурный семпл
Наряду с текстурным объектом узел, который также позволяет манипулировать текстурной информацией в логике материала.
Однако в отличие от предыдущего узла, имеет расширенный функционал, позволяющий проводить дополнительные манипуляции с текстурой, например, разбивать информацию о цвете на три основных канала (RGB), извлекать альфа-канал, а также манипулировать UV-координатами текстуры и многое другое.
Текстурный семпл как правило используется чаще текстурного объекта и несет в себе все его возможности, тогда как текстурный объект применяется в отдельных случаях, например подается в материальные функции не работающие с текстурным семплом напрямую
4. Узлы типа константы
Узла, которые определяют какое-либо число, показатель чего либо. Та что выше - одномерная константа, которая является в чистом виде математической абстракцией. Это просто число.
Его смысл возникает только в контексте, когда мы прикладываем константу к какому либо механизму (логике):
На примере выше константу с нулевым значением я подал напрямую в атрибут базового цвета, что соответствует черному цвету, так как нулевое значение цветового индекса в RGB-поле это как раз черный цвет.
В то же время, если вывести в константу значение 1 (оно является максимальным значением в RGB-поле):
Стоит иметь ввиду, что константа может влиять лишь на монохромный диапазон (от белого к черному), так как по своей природе является одномерной.
Для того, чтобы подать таким образом иной оттенок, нужно подключать все три RGB-канала в одно целое (наподобие радужного спектра) и управлять разными соотношениями трех базовых цветов (красный, зеленый и синий), которые могут дать совершенно разные оттенки:
На изображении ниже представлена 4-х мерная константа, так как помимо трех цветов подключен еще и 4-ый в виде альфа-канала.
Кроме исходного состояния узлов многие из них можно параметризировать.
Например ту же одновекторную (одномерную) константу можно параметризировать в скалярное значение:
Далее придется задать скаляру уникальное имя, которое в свою очередь уже будет передано в экземпляр материала:
И далее создав такой экземпляр материала, напрямую манипулировать значением скаляра без необходимости каждый раз переходит в логику (мастер материал):
Экземпляр наследован от мастера со скаляром с названием “Пример”
Наследование экземпляров не только очень удобный подход, но и крайне практичный. Потому что на базе одной логики (мастер материала) как правило создается несколько инстансов (экземпляров), в каждом из которых одни и те же параметры могут отличаться.
Это часто применяется при создании, например трим листов или D-Buffer декалей, в одном экземпляре я например могу включить эмиссию, а в другом нет.
5. Static Switch Parameter
Статический переключатель по типу булиновой процедуры (элементарная логика переключения с “ложь” на “правда” и наоборот).
На примере ниже вы видите ошибку компиляции, так как статический переключатель не терпит пустых значений в “правду” и в “ложь” обязательно должны подаваться какие-то сигналы.
Этот переключатель по умолчанию передается в экземпляр (инстанс) и нужен для того, чтобы как раз переключаться между какими-либо сложными логиками.
Например, подключать лужи на ландшафтный шейдер или подключать снег.
Все в таком духе:
6. Landscape Layer Blend
Еще один важный узел, расщепляющий логику на слои.
Фактически вы имеете один материал с кучей параметров и функций, но который еще может расщепляться на слои, выбирая которые вы можете красить каким-либо слоем ту или иную поверхность.
Этот механизм используется при создании материалов для ландшафта (вторая часть этой статьи будет посвящена рассмотрению одного из таких материалов):
7. Material Function
Еще одна ценная возможность. Это использование материальных функций.
Подход с их применением позволяет упаковать часть функционала в один блок и переиспользовать в основном графе мастер материала неограниченное количество раз:
На примере ниже, я просто умножил FunctionInput (любое входное значение) на 2, и вывел его наружу:
Входное значение - 1
Выходное значение (результат) - 2
Сам механизм (логика) умножающая входное значение на 2
И вот сама функция выглядит в мастер-материале так:
На вход подается скалярное значение равное 2, проходит через саму функцию, в которой это значением преобразуется (помножается на 2) и поступает на выход в атрибут BaseColor. Таким образом на выходе имеем значение 2 * 2 = 4.
Но это пример очень простой, я бы даже сказал, примитивный.
Как вы догадываетесь, материальные функции создавались разработчиками не ради таких элементарных примеров. В них как правило размещается ключевая и достаточно сложная логика с очень большим количеством параметров и вариантов исхода событий.
Теперь рассмотрим занятный пример ландшафтного материала с применением вышеописанных узлов, а также некоторых других:
В этом примере, начинается все с тайлинга, когда нужно спроецировать текстуру и отрегулировать размер номинального рисунка этой текстуры:
Регулировка размера текстуры как раз упакована в функцию, в которую в свою очередь подается скалярное значение, определяющее размер текстуры и соответственно ее повторяемость на всей площади ландшафта:
Здесь задается номинальный размер всего ландшафта - 1, который просто делится на некое скалярное значение (оно и определяет тайлинг текстуры на поверхности ландшафта) - 2 и 3.
Этот процесс позволяет как бы поделить весь ландшафт как бы на клеточки, размер которых и задается скалярным значением, после чего результат подается на маску, в которой захватываются только каналы R и G, соответствующие координатам X И Y, исключающие координату Z, что дает возможность более адекватно проецировать ПЛОСКУЮ текстуру на поверхность ландшафта.
Идем дальше. И теперь управление тайлингом, а следовательно UV-координатами текстуры подается в несколько функций, в каждой из которых как раз и прописан отдельный слой материала:
Давайте рассмотрим более подробно какую-нибудь функцию слоя.
Обратите внимание, здесь для формирования слоя применяется три текстуры -1, текстуры в свою очередь подаются на еще одну функцию, которая включает в работу различные маски и дополнительные параметры для реализации механизма смешивания:
Далее выводится еще одна функция - 2, которая просто за счет компонентных масок отделяет канал в RGB-поле (это нужно на тот случай):
Ну а узел 3 - называется Make material Attribute:
Такой узел нужен для того, чтобы собрать все атрибуты (baseColor, Normal, Roughness и проч.) в единый сигнал и вывести его на узел, определяющий слои (Landscape Layer Blend). Make Material Attribute зачастую работает в связке с противоположным узлом Break Material Attribute:
И после этого, все необходимые сигналы выводятся на выходы функции, т.е. вот сюда:
Таких функций, определяющих слои несколько и они уже поступают на узел слоев Landscape Layer Blend. А дальше, чтобы разбить сигнал снова на атрибуты как раз и подается Break material Attribute, о котором я писал выше:
Вы справедливо можете спросить, а зачем сначала атрибуты объединять в один сигнал, а затем снова его разбить на составляющие.
А все дело в том, что между этим двумя процедурами проложен слоевик - Landscape Material Attribute, который задает слои, фактически подматериалы.
Таким образом, мы соединили все атрибуты в единое целое и подали на слой, после чего сигнал, в котором заложена информация о принадлежности к какому-либо слою и после разбивается на атрибуты.
Таким образом на выходе мы не просто имеем разные атрибуты, но атрибуты с принадлежностью к какому-либо слою.
Ну а далее уже определяются разные дополнительные механизмы, например лужи:
Зима:
Общая влажность:
И многие такие компоненты реализованы как раз материальными функциями.
Кроме того в ландшафтных материалах зачастую используется спавн растительности и мелких элементов, т.н. грасс тайпы:
Многие особенности материалы мы прошли лишь вскользь.
Причина проста: статья итак вышла большой и чтобы рассмотреть весь материал в деталях со всеми объяснениями потребуется и статья, и целая методичка.
Так что кому интересно приходите ко мне на курс, который уже скоро будет доступен. Там мы исследуем многие такие материалы в подробностях.
Материала очень много и будет очень увлекательно, и полезно!