Визуализация, которая живёт в плеере
Большинство плееров дают анализатор спектра и на этом останавливаются. У rox эти панели есть, есть движок Milkdrop для двадцати лет пресетов, а под ними слой модуляции: именованные сигналы, снятые со звука, направленные во входы шейдеров, которые вы пишете сами, и сохранённые в том же файле, где лежит остальная ваша тема.
Сначала обычные панели
Панель спектра со стилями полос или блоков, градиентами, метками пиков с собственной гравитацией, подписями частот и разделением на зоны, которое анализирует выше и ниже выбранной частоты окнами разного размера, так что каждый конец диапазона сам меняет отзывчивость на разрешение. Полоса волновой формы, которая рисует весь трек по каналам и перематывает туда, куда вы кликнете. VU-метр. Полка обложек, которая крутит их в настоящем 3D. Ничему из этого не нужно ни строчки кода, и именно этим большинство и будет пользоваться.
Пауза замораживает полосы там, где они были, а не даёт им упасть на пол. Звучит мелочью, пока вы не пытаетесь разглядеть тот самый момент, на котором поставили паузу.
Milkdrop, в панели и позади всего
Панель Milkdrop рендерит пресеты через libprojectM в собственном потоке и рисует результат через ту же цепочку шейдеров, что и всё остальное: она стыкуется, уходит во вкладку и отделяется, как любая другая панель, и поверхностный шейдер ложится на неё так же. Положите пакет пресетов в папку, указанную на странице пресетов, Cream of the Crop или оригинальный набор MilkDrop, и нажмите «Пересканировать». Текстуры, идущие внутри пакета, находятся сами.
«Выбрать пресет» открывает браузер в отдельном окне: дерево папок или сетка миниатюр, фильтр, переключатель избранного и навигация с клавиатуры. Клик по пресету сразу загружает его позади окна, так что вы видите настоящий рендер, а не превью. Ротация задаёт, что перебирают «Следующий», «Предыдущий» и смена по таймеру, а блокировка держит один пресет от трека к треку.
Тот же движок работает подложкой позади каждого окна, наложенный на размытую обложку с силой, которую задаёте вы. Пресет может оставить свои цвета, перевернуться под светлую тему, рисовать в палитре или взять цвет играющей обложки, сохранив свои детали, а альбомный оттенок сдвигает тона к обложке. Остановленная очередь гасит его, и поток рендера останавливается, так что простаивающий визуал ничего не стоит.
Шейдеры на четырёх поверхностях
Шейдер rox — это одна фрагментная стадия WGSL. Он может идти по телу одной панели, отдельной панелью Шейдер, наложением поверх всего окна или подложкой, рисующей под всеми панелями, за обложкой. У наложения и подложки есть переключатель, который распространяет их на каждое открытое окно rox. Один и тот же язык, один и тот же блок униформ, одна и та же маршрутизация во всех случаях.
Каждый шейдер получает часы, разрешение, указатель и восемь метазначений, описывающих момент: громкость, где стоит указатель воспроизведения в треке, движется ли звук на самом деле, длину трека и то, насколько тёмной рисуется текущая палитра, так что один шейдер может одеться и под светлое, и под тёмное, а не поставляться под ту тему, против которой его писали.
Панельный шейдер может ещё и прочитать то, что панель действительно нарисовала. Привязка маски отдаёт ему собственную отрисовку панели, повторённую на прозрачности, а панели публикуют форму своего содержимого, так что тень или свечение следуют за вписанной в поля обложкой, а не за пустыми полосами по бокам от неё.
Дальше одной стадии комментарий // @pass делит текст на цепочку до восьми, и каждая может читать предыдущие по имени. Это то, что нужно пирамиде размытия или двухстадийному bloom. Строка // @asset называет картинку для выборки, а // @asset art: @cover привязывает собственную обложку играющего трека и перепривязывает её при смене трека. С приложением идут девять примеров, и каждый показывает свою часть этого контракта, а не девять вариаций одной плазмы.
Направьте панель на файл на диске, и rox начнёт за ним следить. Сохраните в редакторе, и окно уже с ним. Сохранение, которое не компилируется, оставляет на экране последнюю рабочую версию с ошибкой в панели, потому что терять картинку плохой способ узнать, что вы не там поставили точку с запятой.
Сигналы — это та часть, которая отличается
Шейдер с часами внутри — это скринсейвер. Визуализацией его делает то, чем вы его кормите, а в rox это пул именованных сигналов, общий для всего приложения. Вы собираете их в отдельном окне, в разделе «Приложение», рядом с эквалайзером, и оно несёт спектр и транспорт по той же причине, по какой их несёт эквалайзер: полосу выбирают глазом и ухом против того, что вы на самом деле играете.
Пять видов источника. Полоса — это энергия между двумя частотами, тот сигнал, на котором едет нарастание. Уровень — это вся смесь. Атака пульсирует, когда полоса прыгает выше собственного недавнего среднего, и это сигнал, на котором едет удар. Триггер пульсирует, когда полоса пересекает нарисованную вами черту, для материала, где скользящее среднее не успевает опуститься и атака затихает после первого такта. Сумма накапливает другой сигнал со временем и сбрасывается на единице, так что шейдер может читать её как фазу, которая движется, пока музыка громкая, и замирает, пока нет.
У каждого есть сглаживание отклика и порог. Порог — это та настройка, которая себя оправдывает: полоса, едущая на фоновом шуме комнаты, вечно держит каждый привязанный к ней регулятор чуть выше нуля, а порог с кривой над ним отдаёт между ударами тишину. Индикатор рисует необрезанное значение с отмеченной на нём чертой порога, ведь полоса, исчезнувшая под своим же порогом, никак не помогла бы его поставить.
Маршрут привязывает один сигнал к одному параметру с диапазоном выхода: этот сигнал, эта цель, отсюда досюда. Шестнадцать слотов доходят до каждого шейдера, а слоты, к которым ничего не привязано, получают обычный ползунок на странице настроек, так что внешний вид может быть наполовину сыгранным и наполовину выставленным вручную.
Critters как аргумент
Одно из рабочих пространств в коробке — это весь плеер, отрисованный однобитной печатью: упорядоченный дизеринг по каждой поверхности, тона, схлопывающиеся с сабом, и стена шума за панелями, которая движется вместе с песней. Это пять сигналов и четыре шейдера в одном файле, и ничто из этого не является особым случаем в приложении.

Загрузите его из окна приветствия, затем откройте настройки и разберите на части. Остальные.
Запуск чужого шейдера
Шейдеры ездят внутри файлов рабочих пространств, а значит импортированный внешний вид приезжает с чужим кодом.
Ничего не запускается, пока вы не скажете. Исходник каждого шейдера снабжается отпечатком, а список подтверждённых лежит на этой машине и пишется только прямым действием: вы выбрали файл, вы нажали перезагрузку, вы выбрали пресет, вы нажали «Подтвердить». Внешний вид, приехавший в наборе, до тех пор просто лежит с кнопкой под ним. Примеры, которые идут с rox, доверены по построению, ведь они вкомпилированы в бинарник.
Включение открывает окно подтверждения, которое ждёт ответа, а не отсчитывает время, и само это окно никогда не затеняется. Что бы шейдер ни делал с остальным экраном, путь обратно остаётся читаемым.
Что не сделано
- Маршруты доходят до слотов шейдеров и регуляторов панели частиц. Настройки всех остальных панелей — это по-прежнему регуляторы, которые вы ставите рукой.
- Пресеты Milkdrop, а не AVS. Импорта для AVS из Winamp нет. И пресет живёт файлом на вашем диске, поэтому какой из них загружен, остаётся на этой машине, а не переезжает внутри рабочего пространства.
- Нет управляющей поверхности MIDI или OSC. Есть проход наложения и проходы панелей, и ими управляют звук и указатель.
- Проход на всё окно — это настоящий проход GPU каждый кадр. На ноутбуке от батареи это выбор, который вы делаете.
Расстояние между «хочу, чтобы весь плеер вспыхивал на бочке» и готовым результатом — это полоса, порог и маршрут, и ни одному из трёх не нужна пересборка.
Попробуйте на своей коллекции
Ничто здесь никуда не звонит: анализируется тот звук, который и так идёт через плеер. Подробнее о том, что несёт рабочее пространство.