Северное сияние без библиотек
Как устроено небо на сайте AURORA: один шейдер на WebGL, зацикленное время и запасной кадр для слабых устройств.
· 2 мин чтения
Для флагманского концепта нам нужно было живое северное сияние на первом экране. Готовые 3D-библиотеки тянут сотни килобайт, а сиянию не нужна сцена с камерой и светом. Хватило одного полноэкранного треугольника и фрагментного шейдера на чистом WebGL.
Из чего сделано небо
Сияние на фотографиях — это занавесы: у каждого резкий нижний край, вверх уходят лучи, верх светится маджентой. Мы так его и собрали.
- Три занавеса. Высоту нижнего края каждого задаёт фрактальный шум: пять слоёв обычного шума разного масштаба. Отсюда плавные изгибы.
- Разрывы. Второй шум решает, где занавес есть, а где тёмная щель. Без него небо выглядит как ровная зелёная полоса.
- Лучи. Третий шум растянут почти только по горизонтали, поэтому даёт вертикальные штрихи. Его возводим в степень, чтобы яркие лучи были редкими.
- Цвет. Снизу зелёный и бирюзовый, к верху занавеса мешаем маджента. В конце мягкая тонировка, чтобы яркие места не выгорали в белое.
Сияние размытое по природе, поэтому рисуем его в 0,6 от размера экрана и растягиваем средствами CSS. На глаз разницы нет, а видеокарта телефона делает почти втрое меньше работы.
Время по кругу
Превью для карточки на главной хотелось сделать роликом, а не живым WebGL: на странице со списком работ шейдер не нужен. Ролик должен повторяться без шва, значит, через восемь секунд небо обязано вернуться в ту же картинку.
Обычное время для этого не годится: шум просто уедет дальше. Поэтому время в шейдере идёт по кругу в пространстве шума:
float ang = 6.2831853 * u_time / 8.0;
vec2 loop = vec2(cos(ang), sin(ang));
// смещение занавеса: через 8 секунд точка возвращается туда же
vec2 drift = loop * (0.3 + 0.15 * fk);
Точка шума обходит окружность и возвращается в начало. Кадры мы записали прямо из шейдера, по одному, и собрали в ролик: webm весит 472 КБ, mp4 — 549 КБ. Последний кадр отличается от первого не больше, чем два соседних, поэтому шва не видно.
Когда WebGL нет
Сайт не должен ломаться на старом телефоне или у человека, который отключил анимации в системе. Для таких случаев есть неподвижный кадр неба из того же шейдера. Пока WebGL поднимается, вместо пустого фона виден он, а если WebGL недоступен или включено уменьшение движения, он остаётся насовсем. Текст при этом виден сразу, без появлений.
Что получилось
Живое небо, которое чуть тянется за курсором, весит несколько килобайт кода. В локальном замере Lighthouse на мобильном профиле страница концепта набирает 95 баллов производительности, хотя на первом экране работает шейдер.