Bollywood HungamaJanhvi Kapoor, Sreeleela and Siddharth Gupta team up for Umesh Bisht’s thriller, first schedule begins in NainitalInquirerTaal Volcano records 17 earthquakes in 24 hoursCNN TürkTaksitli alışverişlerde yeni dönem: Cep telefonlarında 12 taksit sınırı değiştiPunchPolice remove Rivers DPO after station renovation by suspected cultistsDaily MaverickKATLEHONG MASS SHOOTING: Girl, 11, who survived mass shooting still has bullet lodged near her spineRTP DesportoFrancisco Cabral na final de pares do Masters 1.000 de XangaiThe Jerusalem PostIDF blocks roads leading to Gaza border after Nahala settlers attempt to build outpost overnightEgypt IndependentTemperatures drop 3°C as rain reaches CairoMalay MailFahmi: No Malaysian palm oil companies involved in burning activities in IndonesiaColliderApple TV's New Crown Jewel Officially Continues Streaming DominationSouth China Morning PostChina’s AI boom, self-sufficiency push fuel earnings surge for local chip firmsSky TG24Sciopero scuola e blocco autotrasportatori: giornata di mobilitazione da Nord a Sud. LIVE
The Daily Newsstand · Free, Always
Friday, October 16, 2026

Почему подсветка док-станции Flydigi выглядит дёшево и как я написал свою

Translate

У меня геймпад Flydigi Vader 5 Pro и к нему док-станция Charging Dock 2 Pro (в системе она видна как "Flydigi CD2"). На доке 162 RGB-светодиода, собранных в шестиугольную сетку в форме треугольника, и сами по себе они хорошие: яркие, ровные, с приличной цветопередачей. А вот эффекты из фирменной программы Flydigi Space Station выглядели дёшево: медленные анимации идут заметными ступеньками, градиенты между двумя цветами грязнеют в середине, радуга режется на полосы.

Стало интересно, виновато железо или софт. Спойлер: софт. В итоге получился FlyGlow, открытый редактор подсветки для этого дока. Ниже о том, как устроены фирменные эффекты, как док принимает кадры, что не так с цветом и как сделать всё плавно.

Как Space Station рисует эффекты

Space Station - приложение на Electron, а с железом общается фоновая служба на .NET. Эффекты считаются прямо в JavaScript интерфейса, а служба только передаёт готовые кадры в док. Если открыть код генераторов эффектов, видно всё сразу:

  • Каждый эффект - ровно 50 кадров на цикл. При медленной скорости один кадр держится 100 мс и дольше, поэтому плавный эффект превращается в слайд-шоу.

  • Цвета смешиваются линейно в sRGB. Середина перехода между двумя насыщенными цветами получается тёмной и серой: линейная интерполяция гамма-кодированных значений не соответствует ни физике, ни восприятию.

  • Радуга строится через HSL. HSL неравномерен для глаза: жёлтый и голубой выглядят широкими яркими полосами, синий проваливается.

  • Затухание считается по 8-битным значениям с округлением вниз. На тёмном конце шаг в одну единицу уже заметен глазом, и “дыхание” гаснет рывками.

Важный вывод: сам док эффекты не генерирует. Он просто проигрывает присланный набор кадров. Значит, если прислать кадры лучше, станет лучше и подсветка.

Что умеет док

Протокол дока первым разобрал проект OpenFlydigi (Linux-утилита для Apex 5 и CD2). Я перепроверил всё на своём экземпляре с прошивкой 0.0.3.9.

Параметр

Значение

USB

VID 37D7, PID 6001, HID-интерфейс, отчёты по 64 байта

Светодиоды

162 штуки, 16 рядов: 14, 15, 16, 15, 14, 13 ... 3

Кадров в цикла

до 255 (счётчик в один байт), Space Station отправляет максимум 200

Шаг кадра

период в единицах по 20 мс, то есть максимум 50 кадров в секунду

Яркость

1..100

Загрузка

команда 97 открывает передачу, команда 98 несёт пакеты по 50 байт, каждый с подтверждением

Пакет устроен просто: 5A A5 <команда> <длина> <данные> <контрольная сумма>, где контрольная сумма - восьмибитная сумма байтов от команды до конца данных. Конфиг подсветки - шесть байт заголовка (число кадров, период, яркость, режим, направление, размер палитры) и затем по 486 байт на кадр (162 × RGB).

Пара наблюдений на практике:

  • Один пакет с подтверждением занимает около 9 мс, то есть кадр загружается примерно 85 мс, а цикл из 200 кадров - около 17 секунд. Для живого управления в духе OpenRGB это не подходит, а вот для заранее посчитанной анимации - вполне.

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

  • У Space Station есть ошибка на единицу при подсчёте пакетов: она объявляет
    длина / 50 + 1 пакетов, а отправляет ceil(длина / 50). Числа расходятся, когда длина кратна 50, то есть при количестве кадров, дающем остаток 4 от деления на 25. FlyGlow такие количества просто не использует.

Цвет: линейный свет и OKLab

Значения в sRGB - это не количество света, а гамма-кодированные числа. 50% в sRGB - это примерно 21% света. Поэтому FlyGlow держит всё в линейном свете: так складываются и смешиваются слои, как это делал бы свет.

Для градиентов линейного света мало: глаз воспринимает яркость нелинейно, и переход в линейном RGB тоже выглядит неровно. Для перцептивной интерполяции используется OKLab - цветовое пространство Бьёрна Оттоссона, в котором равные шаги выглядят равными. Смешивание двух цветов выглядит так:

Rgb mix(const Rgb& a, const Rgb& b, float t)
{
    const Lab la = toOklab(a), lb = toOklab(b);
    return fromOklab({la.L + (lb.L - la.L) * t,
                      la.a + (lb.a - la.a) * t,
                      la.b + (lb.b - la.b) * t});
}

Ещё три приёма:

  • Затухание по воспринимаемой яркости. Глаз оценивает яркость примерно как кубический корень от количества света, на этом построена ось L в OKLab. Поэтому для ровного на глаз затухания яркость задаётся в “воспринимаемых” единицах и переводится в линейный свет возведением в куб. “Дыхание” перестаёт резко гаснуть в конце.

  • Радуга из насыщенных основных цветов, интерполированных в OKLab, где опорные точки расставлены пропорционально расстоянию между цветами в OKLab. Оттенок идёт с равномерной скоростью, без широких жёлтых и голубых полос.

  • Гамма вывода настраивается. Светодиод с ШИМ-управлением выдаёт свет линейно от значения, поэтому по умолчанию в док уходят линейные значения: соотношения яркостей совпадают с превью. Для любителей картинки “как в Space Station” есть ползунок.

Восемь бит и дизеринг

Линейные значения хороши всем, кроме тёмного конца: в восьми битах самый тусклый уровень - это уже 1/255, и плавное затухание в темноте снова идёт ступеньками. Помогает временной дизеринг: ошибка округления каждого светодиода переносится на следующий кадр. Анимация зациклена, поэтому прогон делается дважды, и сохраняются результаты второго прохода: ошибка, приходящая в первый кадр, тогда ровно та, что набирается к концу цикла.

Бесшовные циклы

Док крутит анимацию по кругу, поэтому шов между последним и первым кадром заметен сразу. Каждый эффект в FlyGlow - чистая функция от фазы цикла в диапазоне [0, 1): никакого внутреннего состояния, никаких часов. Скорость задаётся целым числом повторов, а не произвольной частотой.

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

double loopNoise(double x, double y, double phase, uint32_t seed, double radius)
{
    const double a = 2.0 * std::numbers::pi * phase;
    return valueNoise4(x, y, radius * std::cos(a), radius * std::sin(a), seed);
}

При phase = 0 и phase = 1 точка на окружности одна и та же, поэтому шов исчезает математически, а не подгонкой. Автотест прогоняет все 21 эффект: нет ли NaN, совпадает ли последний кадр с первым, нет ли резких скачков между соседними кадрами.

Жить рядом со Space Station

Первой версией FlyGlow отправлял кадры через фоновую службу Space Station: её интерфейс общается со службой по именованному каналу \\.\pipe\fcs.sock, сообщения - protobuf с текстовым заголовком. Работало, но выяснилось, что служба обслуживает одного клиента за раз: пока открыто окно Space Station, канал занят им.

Решение оказалось проще: HID-интерфейс дока на Windows можно открыть совместно (FILE_SHARE_READ | FILE_SHARE_WRITE), даже когда его держит служба. Ответы устройства приходят во все открытые дескрипторы, поэтому свои подтверждения приходится отличать по номеру команды, а чужие игнорировать. Теперь FlyGlow пишет в док напрямую, а Space Station спокойно работает рядом и занимается геймпадом. Канал службы остался запасным путём.

Редактор

Остальное - уже интерфейс, C++20 и Qt 6 Widgets:

  • Слои с режимами наложения “Обычный”, “Сложение”, “Экран”, “Умножение”, “Замена светлым”, непрозрачностью и областью, нарисованной кистью.

    Своя анимация. Кисть всегда привязана к ближайшему светодиоду, а размер считается кольцами шестиугольной сетки, так что размер 1 - ровно один диод. Ключевые кадры на таймлайне, между ними интерполяция в OKLab. Левая кнопка рисует, правая стирает.

  • Импорт GIF и видео. Видео декодируется через Media Foundation, без внешних зависимостей. Каждый светодиод усредняет свою шестиугольную ячейку кадра по 19 точкам в линейном свете, а не берёт один пиксель, поэтому мелкие детали не мерцают.

  • Отправка - кнопка с заливкой-прогрессом, около 85 мс на кадр.

  • Интерфейс на английском и русском, переключается на лету без перезапуска.

Что дальше

  • Подсветка геймпадов. У Apex 5 и Vader 5 Pro свой конфиг подсветки, но там всего около 10 кадров на цикл, так что выиграть получится в качестве цветов, а не в плавности.

  • У дока есть команда записи одного кадра, которую Space Station не использует. Если она окажется быстрой, появится живой режим: реакция на музыку или на картинку на экране, а там и интеграция с OpenRGB. Код открыт под MIT, установщик и portable-версия лежат в релизах. Если у вас такой же док с другой прошивкой, отчёт о том, как всё работает, очень поможет.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.