Engine & platform

Искусство, которое движется: Создание анимированных материалов с помощью Shader Graph

JOHN O'REILLY Anonymous
Oct 5, 2018|12 Мин
Искусство, которое движется: Создание анимированных материалов с помощью Shader Graph
Эта веб-страница была переведена с помощью машинного перевода для вашего удобства. Мы не можем гарантировать точность или надежность переведенного контента. Если у вас есть вопросы о точности переведенного контента, обращайтесь к официальной английской версии веб-страницы.

В Unity 2018.2 мы добавили вход "Vertex Position" в Shader Graph, позволяющий настраивать и анимировать сетки. В этой статье я покажу, как можно создавать собственные шейдеры вершинной анимации, и приведу несколько распространенных примеров, таких как шейдер ветра и шейдер воды.

Если вы впервые знакомитесь с Shader Graph, вы можете прочитать статью в блоге Тима Купера, чтобы узнать об основных возможностях, или посмотреть доклад Энди Тача "Введение в Shader Graph" на канале Unity YouTube.

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

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

Скачать пример проекта

Клонировать репозиторий с GitHub или Скачать .Zip с GitHub

Загрузите пример проекта Desert Island Scene, чтобы начать экспериментировать и взаимодействовать с шейдерами самостоятельно! Этот проект содержит все необходимое для начала работы с Shader Graph. Убедитесь, что вы запускаете проект с помощью Unity версии 2018.2 или выше.

Каждый шейдер в Desert Island Scene был создан с учетом индивидуальных особенностей, так что смело начинайте играть со значениями шейдеров в Инспекторе! Каждый объект также имеет файл предварительной настройки, который возвращает значения по умолчанию.

Эта работа лицензирована в соответствии с Creative Commons Attribution 4.0 International License.

Установите Shader Graph

Чтобы использовать Shader Graph, ваш проект должен отвечать следующим требованиям:

  • Работает на Unity версии 2018.2 или выше.
  • Использование новых конвейеров рендеринга Lightweight или High Definition (LWRP рекомендуется для экспериментов из-за более быстрого времени компиляции).
  • В менеджере пакетов должен быть установлен пакет Shader Graph.

Чтобы установить Shader Graph, создайте или обновите проект до версии 2018.2 или выше, перейдите в меню Окно > Менеджер пакетов > Все, найдите Shader Graph в списке и нажмите кнопку Установить.

Если материалы не анимируются в режиме просмотра сцены, убедитесь, что у вас установлен флажок Animated Materials (Анимированные материалы ):

Делаете что-то причудливое с помощью Shader Graph?
Вы можете просмотреть анимированные материалы, нажав на маленькую картинку в левом верхнем углу окна просмотра сцены.
#UnityTips #Unity3D
Основы положения вершин
Положение вершины

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

Сетка в сцене имеет четыре типа пространств:

  • Объект: Положение вершины относительно точки поворота сетки.
  • Вид: Положение вершины относительно камеры.
  • Мир: Положение вершины относительно начала мира.
  • Тангент: Решает некоторые специальные задачи, например, попиксельное освещение.

В раскрывающемся списке узла Position (Положение ) можно выбрать, на какое пространство вы хотите повлиять.

С помощью узла Split мы можем выбрать, на какую ось мы хотим воздействовать.

Узел Split выводит

Узел Split выводит данные на четыре канала, первые три соответствуют нашей оси трансформации (R=X, G=Y, B=Z). В примере выше я разделил ось y объекта и добавил 1, переместив наш объект на 1 по его собственной оси.

Иногда вы можете захотеть переместить объект в мировом пространстве. Для этого выберите World в узле Position, а затем преобразуйте вывод обратно в пространство объекта с помощью узла Transform.

Использование масок

Теперь, когда мы узнали, как перемещать сетку, часто полезно знать, как можно ограничить эффект.

С помощью таких узлов, как Lerp, мы можем смешивать два значения. Вход T - это управляющее значение для Lerp. Когда на нашем входе T - 0 (визуализируется как черный), используется канал A. Когда на нашем входе 1 (визуализируется как белый), используется канал B. В примере ниже ползунок используется для смешивания двух входов. Вместо слайдера можно использовать любой из следующих примеров.

Использование масок
Маска текстуры

С черно-белой текстурой мы можем использовать детализированные формы, чтобы подтолкнуть нашу сетку. В приведенном выше примере видно, что белый цвет обозначает максимальную высоту нашего диапазона, а черный - отсутствие влияния на положение сетки. Это происходит потому, что черные имеют числовое значение 0, и добавление 0 к позиции сетки не сдвигает ее с места.

Чтобы использовать текстуру с вершинной позицией, необходимо использовать узел Sample Texture 2D LOD вместо обычного узла Sample Texture 2D. Текстуры особенно полезны, если вам нужна маска уникальной формы или с определенной степенью падения.

Ультрафиолетовая маска
Маска текстуры

Хотя она похожа на маску текстуры, с помощью UV-маски вы можете выбрать, какую часть сетки вы хотите затронуть, основываясь на UV Unwrap. На скриншоте выше я использую ось u UV для создания градиента слева направо. Чтобы сместить градиент, используйте узел Add, чтобы увеличить силу - узел Multiply, а чтобы увеличить спад - узел Power.

Цветовая маска вершин

Каждая вершина хранит единицу информации Vector3, которую мы обозначаем как Vertex Colour. Используя пакет Poly Brush, мы можем напрямую рисовать цвета вершин в редакторе. Также можно использовать программы для 3D-моделирования (например, 3ds Max, Maya, Blender, 3D Coat или Modo) для назначения цветов вершин. Стоит отметить, что по умолчанию большинство программ для 3D-моделирования экспортируют модели с максимальным значением RGB, присвоенным каждой вершине.

На скриншоте выше узел Vertex Colour разделен на красный канал(R), затем подключен к каналу T узла Lerp, выступающего в качестве маски. Канал A узла Lerp используется, когда на входе 0, а канал B - когда на входе 1. На практике вышеописанная установка добавит 1 к оси y только в том случае, если вершинам присвоен красный цвет.

Маска для ориентации в мире
Маска для ориентации в мире

Используя узел Normal Vector, мы можем маскировать входные данные по ориентации граней сетки. Опять же, узел Split позволяет нам выбрать, на какую ось мы хотим повлиять (R=X, G=Y, B=Z). На скриншоте выше я делаю маску по оси y, так что только те грани, которые направлены вверх, являются положительными. Важно использовать узел Clamp, чтобы отбросить все значения, которые не находятся в диапазоне от 0 до 1.

Маска положения в мире
Маска положения в мире

Эта серия узлов маскирует вход, если позиция объекта находится выше мировой позиции 0 по оси y.

Свойства
Свойства

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

Свойства позволяют изменять значения шейдера после его компиляции. Чтобы создать свойство, нажмите на символ + в Blackboard (изображен справа). Существует шесть типов недвижимости:

  • Векторы (от 1 до 4): Строка значений, с возможностью использования ползунка для Vector1.
  • Цвет: RGB-значения с выбором цвета, а также дополнительная версия HDR.
  • Texture2D (и Texture2D Array): Образец 2D-текстуры
  • Текстура 3D: Образец 3D-текстуры
  • Cubemap: Сгенерированный образец Cubemap
  • Булево: Выключить или включить. Эквивалент 0 или 1.
Прикладные примеры
Развевающийся флаг

Шейдер флага перемещает синусоиду в пространстве объекта по флагу, используя UV-маску, чтобы сохранить левую сторону неподвижной.

Ультрафиолетовая маска

Изображение в полном разрешении

УФ-маска инвертируется и умножается на себя, чтобы создать плавный градиент по оси y. Он используется для того, чтобы отогнуть центр флага от весла.

В пространстве объекта генерируется синусоидальная волна со свойствами, позволяющими управлять амплитудой, частотой и скоростью волны. Волна маскируется УФ-маской по оси x, чтобы левая сторона флага оставалась неподвижной.

Выведя градиентный шум в функцию Step, а затем в порог Alpha Clip, мы можем отбросить несколько пикселей, чтобы разорвать флаг.

Ветреная трава и пальмовые листья

Шейдер ветра использует панорамирование градиентного шума в мировом пространстве вдоль одной оси, чтобы мягко толкать и тянуть листья и траву.

Изображение в полном разрешении

Используя положение мира, мы разместим градиентный шум по осям y и x. Используя Vector2, мы можем управлять скоростью и направлением смещения.

Свойства используются для контроля плотности и прочности офсета. Вычитание 0,5 из значения Gradient Noise гарантирует, что сетка будет одинаково толкаться и тянуться.

Для того чтобы основание листьев и травы оставалось неподвижным, используется УФ-маска. Наконец, узел Transform используется для преобразования положения в мире в положение объекта.

Койский моллюск

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

Койский моллюск

Изображение в полном разрешении

Введя положение объекта GameObject и положение камеры в узел Distance, мы можем создать маску. Узел "Один минус" инвертирует расстояние так, что мы получаем положительное значение, когда находимся близко к моллюску. Узел Clamp отбрасывает любые значения выше 1 и ниже 0.

Эта УФ-маска вращает только верхнюю часть моллюска, но в большинстве случаев цветовая маска вершин будет проще и гибче.

Узел Lerp используется для смешивания закрытого и открытого моллюска. Вращение применяется к осям y и z объекта GameObject. Вращение вокруг оси x.

Плавающая рыба

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

Плавающая рыба

Изображение в полном разрешении

Создайте синусоиду в пространстве объекта вдоль оси y и оси z со свойствами, управляющими частотой и скоростью волны.
Поскольку мы используем как ось x, так и ось y, рыба колеблется по ширине и по высоте.

Умножьте выходной сигнал синусоиды, чтобы регулировать амплитуду/расстояние/силу колебаний, и добавьте его к оси x объекта.

С помощью узла Lerp замаскируйте переднюю часть рыбы, используя ось x УФ-канала. Используя узел Power со свойством, мы можем перенести эффект колебания на заднюю часть рыбы.

Океанские волны

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

Океанские волны

Изображение в полном разрешении

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

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

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

Генерация синусоидальных волн
Генерация синусоидальных волн

Изображение в полном разрешении

Разделив оси x и z, мы генерируем волны в двух направлениях. Два множителя используются для настройки влияния каждой волны. Например, умножение канала Z на 0 выведет синусоиду исключительно по оси x.

Разделив узел World Position на ось x и ось z, а затем объединив их в Vector2, мы получим UV-пространство в мировом пространстве. Это позволяет ориентировать плоскость градиентного шума по всему миру. Добавляя этот вывод ко времени, мы смещаем синусоидальные волны, помогая разбить прямые линии.

Узел Sine использует мировое пространство и время для генерации простой синусоиды, а чтобы сделать ее вершинами, мы используем абсолютный узел, чтобы перевернуть отрицательные значения. Узел One Minus затем инвертирует эти значения так, чтобы кончики волн оказались вверху.

Дальнейшее чтение

Если вы хотите узнать, как начать работу с Shader Graph, то выступление Энди Тача на GDC - отличное место для начала. Если вы ищете другие примеры Shader Graph, Энди также имеет библиотеку примеров, доступную на GitHub.

Подробную документацию по Shader Graph, включая описание каждого узла, можно найти в Shader Graph Developer Wiki на GitHub. Присоединяйтесь к разговору на нашем форуме Graphics Experimental Previews! И наконец, если вы делаете что-то крутое с помощью Shader Graph, я буду рад это увидеть! Не стесняйтесь связаться со мной в Twitter @John_O_Really.