emil28092005 92e8b287a3 Render the ice as long videos and play them as wallpapers
render_wallpaper.py drives headless Firefox frame by frame (four at a time,
resuming where it stopped), then ffmpeg. Thirty seconds at 30 fps is exactly
one plasma cycle, so frame 900 meets frame 0 and the loop has no seam.

plasma-plugin/dev.emil.video is a minimal Plasma 6 video wallpaper: one file
per screen, filling the screen, looping. H.264 is encoded Baseline because
Qt here decodes through openh264, which rejects High profile and leaves a
frozen frame; a new source also has to be played explicitly.

The #shot hash learned info=0 to hide the on-screen hint for renders.
2026-10-31 01:22:16 +03:00
2026-10-30 21:33:18 +03:00
2026-10-30 21:33:18 +03:00

Сквозь лёд

Плазма, текущая за толстой плитой прозрачного голубого льда. Три самостоятельные страницы, каждая — один HTML-файл без внешних зависимостей (WebGL1 + GLSL ES 1.0).

  • ice_plasma.html — просто плазма за льдом.
  • ice_object.html — в лёд вморожен огранённый кристалл, преломлённый вместе со льдом.
  • ice_fish.html — тёмные силуэты рыб с холодными голубыми глазами проплывают сквозь плиту.

Открыть любой файл в браузере. Мышь — параллакс, − / = — скорость. Цикл плазмы 30 с.

Рендеры

Плазма за льдом

Плазма за льдом

Огранённый кристалл вморожен в плиту: лёд преломляет его так же, как всё за собой

Кристалл вморожен в лёд

Рыбы: тёмные силуэты с холодными голубыми глазами

Рыбы вморожены в лёд

Кадры сняты с текущих шейдеров в 1280×720; время в них зафиксировано параметром #shot&t=… (см. «Проверка»). Сами страницы живые: плазма течёт, рыбы проплывают, кристалл стоит вмороженный и преломляется.

Как устроено

Два прохода на кадр:

  1. Сцена (6_ice_plasma.frag, 8_ice_scene.frag, 10_ice_fish.frag) — плазма рисуется в атлас 4×2 из восьми листов, каждый лист — свой слой на своей глубине. Глубина записывается в альфу: (0.42 + layer * 0.26) / 2.6. Там, где вместо плазмы твёрдый объект (кристалл, рыба), в альфе лежит покрытие, а не глубина.
  2. Лёд (7_ice_over.frag, 9_ice_over_obj.frag, 11_ice_over_fish.frag) — для каждого слоя по его глубине считается путь луча во льду, отсюда своё преломление, свой параллакс и своё поглощение exp(-SIGMA * path). Поверхность — неподвижный рельеф с трещинами; трещины дают ступеньку в склоне и рвут плазму на гранях.

Листы с объектами хранят покрытие вместо глубины, поэтому пасс 2 берёт для них глубину по номеру листа, а не из альфы.

Сборка

python3 build_plasma.py                                            # -> ice_plasma.html
python3 build_plasma.py 8_ice_scene.frag     9_ice_over_obj.frag  ice_object.html
python3 build_plasma.py 10_ice_fish.frag    11_ice_over_fish.frag ice_fish.html

build_plasma.py вставляет оба шейдера в шаблон страницы. После правки шейдеров страницу надо пересобрать — HTML сам по себе не обновляется.

Обои

Готовые рендеры с рыбами — по файлу на монитор (в репозиторий не входят, они тяжёлые):

файл экран размер
~/Videos/wallpapers/ice_fish_2560x1080.mp4 DP-2, ультравайд 110 МБ
~/Videos/wallpapers/ice_fish_2560x1440.mp4 HDMI-A-1 112 МБ

30 секунд, 30 fps, петля бесшовная: кадр 900 совпадает с кадром 0, потому что цикл плазмы ровно 30 с. Профиль H.264 — Baseline: Qt на Fedora декодирует через openh264, который отвергает High profile и молча оставляет замерший кадр.

Пересобрать:

python3 render_wallpaper.py ice_fish.html ~/Videos/wallpapers/ice_fish_2560x1440.mp4 2560 1440 30 30

Скрипт гонит кадры в headless Firefox по четыре за раз, кладёт их в *.frames/ (можно удалить) и кодирует через h264_nvenc. Повторный запуск продолжает с места обрыва.

Обоями видео ставит плагин dev.emil.video (исходники — plasma-plugin/dev.emil.video/, установленная копия — ~/.local/share/plasma/wallpapers/dev.emil.video/). Он проигрывает файл из своего конфига, заполняя экран, и зацикливает его:

kpackagetool6 --type Wallpaper -i plasma-plugin/dev.emil.video

Дальше — правый клик по рабочему столу → «Настроить рабочий стол…» → тип обоев Video Wallpaper → путь к файлу. Настройки у каждого экрана свои.

Проверка

python3 -m unittest test_ice

Рендерит ice_plasma.html в headless Firefox и проверяет, что кадр не пустой, плазма движется, цикл замыкается и мышь меняет картинку. Нужны Firefox и Pillow; сами страницы — нет.

Кадр вручную: firefox --headless --screenshot=/tmp/x.png "file://$PWD/ice_fish.html#shot&t=8". Параметр t фиксирует время, mx/my — позицию мыши.

Оговорки

  • 9_ice_over_obj.frag и 11_ice_over_fish.frag — копии 7_ice_over.frag: правки рельефа и преломления льда надо переносить во все три файла.
  • debug_fish.frag + debug_fish.html — плоский рендер силуэтов рыб для отладки формы.
  • renders/*.jpg — картинки для этого README, к сборке отношения не имеют.
  • render_wallpaper.py — кадры + ffmpeg, длинное видео для обоев.
  • plasma-plugin/dev.emil.video — минимальный видео-обои плагин для Plasma 6.
  • build.py собирает playground.html со всеми .frag подряд, render.py/shot.py — старые вспомогательные скрипты.
S
Description
No description provided
Readme
2.7 MiB
Languages
HTML 53.9%
GLSL 30.4%
Python 14.6%
QML 1.1%