Для начала можно посмотреть в их
исходники. Беглый просмотр кода показывает основной план действий:
- Создать плоскость с кастомным материалом. Вершинный шейдер стандартный нейтральный, который ничего необычного не делает, только сохраняет координаты UV, чтобы их во фрагментном использовать. Фрагментный будет содержать в себе всю логику. Это частенько так делается в 2D-эффектах.
- Во фрагментный шейдер передать две текстуры. Одна обычная, для фона. Вторая - карта смещений для пикселей. Displacement map по-нашему. Берем пиксели из фона, смещаем по данным из карты смещений - получаем результат.
- Нарисовать текстуру для фона. В их случае она делается из кадров видео, т.е. вот этот бултыхающийся градиент на фоне в их случае заранее заготовлен. И, к слову, видно, что он шакалится. Но с точки зрения производительности видео тут - это хорошая идея. Генерирование клякс-градиентов - требовательная в вычислительном плане задача.
- Нарисовать displacement map по какой-то логике, завязанной на положение мыши. Тут большой простор для экспериментов. В их случае они используют отдельную сцену с кучей объектов, у которых меняются расположение и прозрачность в зависимости от положения мыши и просто со временем. Там много магических чисел. Вероятно все подбиралось наугад. Как это обычно и происходит. И потом они рендерят эту сцену в текстуру, которая передается в уже упомянутый шейдер. Можно было бы на 2D канвасе ее рисовать. Но с трехмерной сценой в таких задачах проще работать, хотя это поначалу кажется контринтуитивным.
Все остальное в коде - обвязка, чтобы это организовать в рамках Three.js. В этом конкретном сценарии этот инструмент выглядит слегка избыточными. Можно было бы взять какую-нибудь альтернативную легковесную библиотеку, но по сути делать пришлось бы то же самое.
От этого вполне можно оттолкнуться и сделать что-то подобное в рамках своих инструментов/требований/дизайнов.