Шейдер поточного движения или Флоумапинг 🌊

Что такое флоумапинг?

Техника шейдинга для создания эффекта движения текстуры.

Что требуется для реализации:

🖼 Опыт написания шейдеров

🔣 Базовые знания математики

🍟 Чачка пипсов

Для чего мне это?

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

Как реализовать?

Основной компонент флоумап шейдера - одноименная текстурная карта, где цвет пикселя является репрезентацией направления движения.

Как цвет пикселя превращается в направление(вектор)?

Предположим, что у нас есть пиксель с RBG(Красный, Зеленый, Синий) каналами, в таком случае информация о цвете пикселя представляет из себя vec3(R,G,B) компонент, каждый из каналов в котором содержит в себе float значение от 0.0 до 1.0.

При смешивании различных значений каналов мы получим новый цвет.

Шейдер поточного движения или Флоумапинг 🌊

При помощи цвета пикселя мы можем описывать vec3 значения.

Представим получившееся значение в виде точки в пространстве

Шейдер поточного движения или Флоумапинг 🌊

Мысленно построим из нулевой координаты до получившейся точки вектор

Шейдер поточного движения или Флоумапинг 🌊

Подобные вектора являются набором пикселей для флоумапы, которую мы в итоге представим в виде целой текстуры

Шейдер поточного движения или Флоумапинг 🌊

Для работы с 2D текстурой в ее плоскости нам понадобятся только 2 канала R,G, поэтому флоумапа будет состоять только из 2 цветов, Зеленого и Красного соответственно.

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

Шейдер поточного движения или Флоумапинг 🌊

Поэтому в дальнейшем значения от 0.0 до 1.0 будут ремапится от -1.0 до 1.0, в этом случае при написании флоумапы значение vec2(0.5,0.5) условно описывает отсутствие движения, т.к. после ремапинга его значение будет приведено к vec2(0.0,0.0).

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

В примере используется 8 битное значение цвета, 255 условно равно 1.0
В примере используется 8 битное значение цвета, 255 условно равно 1.0

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

Шейдер поточного движения или Флоумапинг 🌊

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

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

Для микширования потоков важно, что оба временных потока в сумме всегда равны единице, т.к. смешивать мы будем их при помощи lerp() или mix() в зависимости от среды. Добиться этого можно при помощи оффсета одного из потоков на 0.5 и вычитанием из каждого целой части при помощи floor()

Graphing
Graphing
ShaderGraph
ShaderGraph
GLSL
GLSL

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

Для этого мы воспользуемся математической хитростью. Нам известно, что каждый из потоков растет от 0.0 до 1.0 и достигнув предельного значения воспроизводит цикл повторно.

Но при смешении потоков подобным образом мы получим обрыв в начале каждого цикла.

Нам же необходимо создать функцию, которая сперва растет от 0.0 до 1.0, а после уменьшается от 1.0 до 0.0.

Чтобы добиться этого результата, нам нужно совершить пару манипуляций:

1.Возьмем значение первого потока и вычтем из него 0.5

Шейдер поточного движения или Флоумапинг 🌊

2.Приведем из получившегося значения отрицательные величины к положительным, при помощи abs(), возвращая число по модулю

Шейдер поточного движения или Флоумапинг 🌊

3.Умножим получившееся значение на 2 и получим желаемый результат

Шейдер поточного движения или Флоумапинг 🌊
ShaderGraph
ShaderGraph
GLSL
GLSL

Дело за малым: при помощи lerp() или mix() внесем в него первое и второе !семплированное! флоумапами изображение и будем ссылаться на значение которое мы получили после математических манипуляций.

ShaderGraph
ShaderGraph
GLSL
GLSL

Настраиваем переменные под желаемый вид и отрываем шампанское, теперь мы можем в флоумапинг. 🍾🍾🍾

Благодарю за прочтение и, разумеется,

Ссылка на Git содержит UnityPacage с собранным в ShaderGraph шейдером и Шейдер, написанный с использованием GLSL, который вы можете использовать, например, для web.

Вдохновляющая статья о реализации этого трюка https://johnsietsma.com/2015/12/01/flow-maps/

Онлайн редактор флоумап https://cables.gl/p/ntZfmv

Если у вас есть желание поддержать автора статьи, то вы можете:

-Бахнуть по кнопке лайк, чтобы она взорвалась ❤

-Поделиться этой статьёй с людьми, которым интересна тема компьютерной графики.

-Подписаться на мои проекты:

https://vk.com/shakoretka - вк паблик в котором я делюсь своими знаниями, творчеством и вещами которые нахожу интересными(в основном это игры и геймдев)

https://www.twitch.tv/shakoretka - твич канал на котором я периодически провожу трансляции игр и разработки, а также активно общаюсь с гостями в чате <3

https://dtf.ru/u/294992-shakoretka - блог на DTF в котором я публикую статьи

-Оставить фидбек под статьёй и пожелания о топиках, которые были бы вам интересны.

-Типнуть на кофеёк можно по ссылке на DonationAlerts

177177
33 комментария

Красавчик, хорошо написано!

5
Ответить

ты нихуя не понял

3
Ответить

Благодарю 😳

Ответить

Чачка пипсовДобавил в лист с "Филиное куре".

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

2
Ответить

Спасибо ❤️ Абсолютно солидарен, да и материала по подобным трюкам не так много. Могу порекомендовать этот ресурс в котором описано множество полезных трюков https://learnopengl.com/Advanced-OpenGL/Depth-testing

3
Ответить

Спасибо за лонг.

2
Ответить

Спасибо за интерес

3
Ответить