Files
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

114 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Сквозь лёд
Плазма, текущая за толстой плитой прозрачного голубого льда. Три самостоятельные
страницы, каждая — один HTML-файл без внешних зависимостей (WebGL1 + GLSL ES 1.0).
- `ice_plasma.html` — просто плазма за льдом.
- `ice_object.html` — в лёд вморожен огранённый кристалл, преломлённый вместе со льдом.
- `ice_fish.html` — тёмные силуэты рыб с холодными голубыми глазами проплывают сквозь плиту.
Открыть любой файл в браузере. Мышь — параллакс, `−` / `=` — скорость. Цикл плазмы 30 с.
## Рендеры
*Плазма за льдом*
![Плазма за льдом](renders/ice_plasma.jpg)
*Огранённый кристалл вморожен в плиту: лёд преломляет его так же, как всё за собой*
![Кристалл вморожен в лёд](renders/ice_object.jpg)
*Рыбы: тёмные силуэты с холодными голубыми глазами*
![Рыбы вморожены в лёд](renders/ice_fish.jpg)
Кадры сняты с текущих шейдеров в 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 берёт для них глубину
по номеру листа, а не из альфы.
## Сборка
```sh
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 и молча оставляет замерший кадр.
Пересобрать:
```sh
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/`). Он проигрывает
файл из своего конфига, заполняя экран, и зацикливает его:
```sh
kpackagetool6 --type Wallpaper -i plasma-plugin/dev.emil.video
```
Дальше — правый клик по рабочему столу → «Настроить рабочий стол…» → тип обоев
Video Wallpaper → путь к файлу. Настройки у каждого экрана свои.
## Проверка
```sh
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` —
старые вспомогательные скрипты.