Шейдер тумана

Шейдер тумана

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

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

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

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

Настройки

Это неосвещенный шейдер, созданный в LWRP (облегченном конвейере рендеринга). Он также должен работать в URP (универсальном конвейере рендеринга, который был переименован в LWRP в более новых версиях). Используемые узлы также должны поддерживаться в HDRP (конвейере рендеринга высокой четкости), но я не проверял.

В объекте (Облегченный/Универсальный) конвейер рендеринга опция Текстура глубины должна быть включена, чтобы работал узел Глубина сцены (или вы можете переопределить значение в камере).

На Главном (Master) узле установите параметры в режим прозрачного рендеринга и альфа блендинг. Не забудьте также установить AlphaClipThreshold равным 0, так как мы не хотим отбрасывать пиксели с альфой.

Детальный разбор

Чтобы создать эффекты тумана, нам нужно сэмплировать глубину текстуры с камеры. Шейдерный граф имеет узел Глубина сцены, который будет обрабатывать это и еще делать для нас преобразования. Используя режим сэмлирования Eye, он выведет линейную глубину в единицах измерения пространства наблюдения. Вы можете прочитать больше об узле глубины сцены в посте Scene Color & Depth Nodes.

Далее нам нужна глубина до поверхности плоскости. Для этого мы можем взять альфа/w компонент узла Screen Position в режиме Raw. Не слишком важно знать, почему это глубина объекта, но я полагаю, что это связано с тем, как положения 3D-объектов преобразуются в координаты экрана с помощью матрицы модель-вид-проекция. Однако важно, чтобы мы установили для узла значение Raw, поскольку в режиме по умолчанию каждый компонент делится на это значение альфа/w, включая сам компонент альфа/w. Обычно это называется «перспективным делением» — оно преобразует координаты пространства отсечения (полученные после применения матрицы модель-вид-проекция) в нормализованные координаты экрана, отображая трехмерную перспективу на 2D-экране.

настройки глубины в пространствах

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

Пример 1 (Простой)

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

Прежде чем мы включим это в альфа, было бы хорошо, если бы мы могли как-то контролировать плотность тумана. Мы можем сделать это с помощью узла Multiply (или Divide, если вы предпочитаете использовать значения плотности как 2 или 3 вместо 0,5 и 0,33). Мы также должны поместить результат в узел насыщения (Saturate), чтобы зафиксировать значения в диапазоне от 0 до 1, так как значения больше 1 могут привести к очень ярким артефактам, особенно при использовании пост-эффекта свечения.

Наконец, чтобы изменить цвет тумана, мы создаем свойство Color, чтобы использоватьего дляввода цвета на Главном узле. Я также беру альфа-компонент нашего свойства и умножаю его на насыщенный результат, чтобы учитывалось альфа-значение цвета. Убедитесь, что альфа-компонент цвета тумана (Fog Color) в инспекторе установлен на 1, иначе эффект будет невидимым.

шейдер тумана - граф из примера 1

Пример 2 (Точный)

Чтобы туман был виден в правильном направлении, мы можем вычислить мировое положение координаты глубины сцены и использовать его для создания тумана, используя нормальное направление плоскости/квада.

Создайте узел View Direction, установленный на мировое пространство. Это позволяет получить вектор от положения пикселя/фрагмента до камеры. Величина вектора — это расстояние (между камерой и фрагментом), но это не то же самое, что глубина. Глубина — это расстояние от положения фрагмента до плоскости, которая перпендикулярна камере. Получается треугольник, как показано на рисунке.

(Примечание: я взял это изображение из своего поста про шейдер воды, поэтому не обращайте внимания, что оно говорит «положение поверхности воды». Это положение пикселя/фрагмента на кваде/плоскости, к которому применяется шейдер. Технически стрелка также должна идти и в противоположном направлении, так как направление обзора идет от фрагмента к камере, но положение вещей все равно должно стать понятнее).

расстояние до объекта в сцене

Чтобы восстановить положение в мировых координатах, нам нужно масштабировать этот вектор к положению сцены позади квада/плоскости. Глубину Scene Depth и положение сцены, которые нам нужны, создает еще один показанный на рисунке треугольник. Чтобы получить вектор до положения сцены, мы можем использовать отношение двух треугольников, которое получают путем деления Направления Просмотра на Необработанное Экранное Положение W/A Глубины и затем умножения на Глубину Сцены. Затем мы можем вычесть мировое положение камеры из узла Камера, чтобы получить мировое положение сцены.

Положение в мировом пространстве на основе глубины

Примечание: расчет положения сцены в мировых координатах на основе значений глубины полезен и для других эффектов (например, см. пост Water Shader Breakdown), но обратите внимание, что этот метод работает только для объектов в сцене, он не будет работать с экранными шейдерами для эффектов пост-обработки, например.
Также полезный совет: вы можете взять результат этого вычисления, поместить его в узел Fraction и поместить его в Color на главном узле, чтобы помочь визуализировать положения.

Получив мировое положение сцены, мы можем теперь справиться с туманом. Чтобы убедиться, что туман нарисован в правильном направлении, мы можем трансформировать его положение в объектное пространство и скалярно перемножить его с приведенным вектором нормалей в объектном пространстве. Так как вектор нормали направлен наружу от плоскости, нам также нужно перевернуть результат скалярного произведения (или перевернуть вектор нормали, входящий в скалярное произведение).

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

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

Наконец, чтобы изменить цвет тумана, мы создаем свойство Color для использования в качестве ввода цвета на Главном узле. Я также беру альфа-компонент нашего свойства и умножаю его на насыщенный результат, чтобы учитывалось альфа-значение цвета. Убедитесь, что альфа-компонент цвета тумана в инспекторе установлен на 1, иначе эффект будет невидимым.

Туман просматривается по нормали

Если у вас есть какие-либо комментарии, вопросы или предложения, пожалуйста, напишите мне в Твиттере @Cyanilux, и если вам понравилось читать, поделитесь ссылкой с другими!

Источник: https://cyangamedev.wordpress.com/2019/12/05/fog-plane-shader-breakdown/

Понравилась статья? Поделиться с друзьями:
Автор natalya
Переводит для Вас самые интересные статьи про разработку игр. По образованию физик-программист. Техническими переводами начала подрабатывать еще на старших курсах и постепенно это переросло в основное занятие. Интересуется гуманитарными технологиями, пробует себя в журналистике.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *