deus

Блог

Аудиореактивный шейдер на GLSL: свой визуализатор музыки в браузере

Deus Studio: исходный код шейдера Deus Rainbow v2 слева, живое превью справа и сгенерированные параметры под превью.

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

Обычно сложнее всего не сам шейдер, а всё вокруг: захват звука, БПФ, сглаживание, поиск долей и ударов, передача значений в WebGL. Deus Studio берёт это на себя — открываете редактор в Chrome и сразу занимаетесь картинкой.

Что такое Deus Studio

Deus Studio — редактор GLSL внутри расширения Deus, подключённый к настоящему движку Deus. Вы пишете фрагментный шейдер и сразу видите, как он реагирует на вкладку, которую слушает Deus, или на аудиофайл с компьютера. Превью использует те же uniform-переменные, анализ звука и рендерер WebGL 1, что и визуализатор, так что в превью вы видите ровно то, что заиграет в Deus. Studio входит в бесплатный тариф Free.

Чтобы открыть редактор, запустите визуализатор для вкладки (см. инструкцию про любую вкладку) и выберите в его меню «Создать › GLSL». Начать можно с шаблона «Заготовка», с «Обзора аудиовходов», который рисует каждый звуковой вход в виде индикатора, или с редактируемой копии любого из 70 встроенных WebGL-пресетов. Оригинал при этом не меняется.

Какие данные получает шейдер

Studio работает с GLSL ES 1.00 и функцией mainImage в стиле Shadertoy. Deus в реальном времени передаёт каждому шейдеру набор uniform-переменных; их имена используются напрямую, объявлять ничего не нужно. Самые полезные:

  • u_resolution — размер рендера в пикселях, u_time — секунды с запуска пресета.
  • u_bass, u_mid, u_treble, u_level — басы, середина, верха и общая громкость, нормализованные в диапазон 0–1.
  • u_kick, u_snare, u_hihat — детекторы бочки, малого барабана и хай-хэта, 0–1. u_attack резко растёт на каждом новом звуке, u_bass_pulse — затухающий импульс на ударах баса.
  • u_level_integral — часы, которые идут быстрее, когда музыка громче. Используйте их вместо u_time, чтобы движение следовало за треком.
  • u_frequency[32] и u_waveform[32] — спектр от басов до верхов и форма волны, по 32 значения.
  • u_note_color, u_note_intensity[12] и другие u_note_* — анализ нот по 12 звуковысотным классам, от C до B.

Работают и iTime, iResolution и iFrame из Shadertoy, так что код оттуда переносится с меньшим числом правок. Наведите курсор на любое имя с u_ в редакторе — появится подсказка и текущее значение; на вкладке «Входы» все они собраны со значениями в реальном времени.

Первый аудиореактивный шейдер

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

// Кольцо дышит с басом и подпрыгивает на бочке.
uniform vec3 u_tint; // @color #ff2bd6 label="Tint"

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  // Координаты от центра: y от -1 до 1.
  vec2 p = (fragCoord * 2.0 - u_resolution) / u_resolution.y;
  float r = length(p);
  float a = atan(p.y, p.x);

  float radius = 0.35 + u_bass * 0.35 + u_kick * 0.15;
  float ring = 1.0 - smoothstep(0.0, 0.04, abs(r - radius));

  // Полосы крутятся быстрее, когда музыка громче.
  float stripes = 0.6 + 0.4 * sin(a * 8.0 + u_level_integral * 2.0);

  vec3 color = u_tint * ring * stripes;
  color += u_tint * u_hihat * 0.25 * (1.0 - smoothstep(0.0, 0.6, r));
  fragColor = vec4(color, 1.0);
}

Несколько деталей. Дробные литералы пишутся с точкой: 1.0, а не 1. Комментарий // @color превращает u_tint в выбор цвета — и в Studio, и на панели «Настроить» визуализатора. Ползунки устроены так же: uniform float u_speed; // @param 0 3 1 даёт ползунок от 0 до 3 со значением 1 по умолчанию, а // @toggle 1 — переключатель. Каждый элемент управления — одна строка в коде, поэтому он всегда остаётся с шейдером.

Элементы управления без набора кода

Писать такие комментарии вручную не обязательно. Выделите число в коде или цвет vec3 и нажмите «Сделать ползунок» — он появится и в Studio, и на панели «Настроить». У цветовых литералов есть образец цвета, по которому можно кликнуть, а ошибки компиляции отмечаются на тех строках, где они возникли.

Раздел «Настроить» для Audio Terrain v2: описание и рейтинг, список цветов, переключатель «Случайное движение» и ползунки высоты и частоты волн, числа стен, вращения камеры и закрутки глубины.
Элементы управления из кода появляются на панели «Настроить» визуализатора.

Смотрите, что слышит шейдер

Вкладка «Аудио» показывает сырой и нормализованный спектр и последние 12 секунд уровня, басов, середины, верхов, атак и распознанных ударов барабанов — с подписью uniform-переменной, которая их читает. С этим настраивать намного проще: если кольцо почти не двигается, видно, доходит ли u_bass до 1.0 на этом треке, и формулу можно подправить. Источник звука — вкладка, которую захватывает Deus, или трек с вашего компьютера.

Проходы рендера, обратная связь и другие имена

Комментарии задают и рендер: // @pass buffA scale=0.5 добавляет проход, который читается как uniform sampler2D buffA;, // @feedback 0.09 плавно гасит прошлый кадр вместо очистки — получаются шлейфы, а // @fps 30 ограничивает частоту кадров. Если вы переносите шейдер в стиле Synesthesia, движок задаёт и имена вроде syn_BassLevel, syn_Hits или TIME — объявите их в коде, чтобы использовать.

Сохраните шейдер в Deus

Нажмите «Сохранить» (⌘S), и пресет появится в «Пресеты › Мои пресеты» с миниатюрой из превью, или «Сохранить и включить», чтобы визуализатор сразу переключился на него. Несохранённые правки переживают перезагрузку как черновик, а ваши пресеты хранятся локально в браузере.

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