Files
airdef/docs/HD-RENDERER.md
T
chexit 65dd84646a
build / mod (push) Successful in 3m20s
docs: HD renderer architecture, status and plan, kept up to date for handover
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:55:15 +03:00

15 KiB
Raw Blame History

HD-рендер AirDef: устройство, статус, план

Документ для передачи работы (человеку или агенту). Ведётся по ходу разработки: каждый этап, попавший в main, отмечается здесь вместе с коммитом. Если что-то в коде расходится с этим текстом — прав код, а текст надо поправить.

Что это

HD — третий пресет графики мода (/airdef shader off|on|hd): отложенное освещение в стиле шейдерпаков (BSL/Complementary-класс), но написанное с нуля внутри нашего форка Horizon (Minecraft 26.3 на Rust/wgpu). Код шейдерпаков (BSL, Complementary, Photon, Iris/OptiFine) не копируем: их лицензии запрещают перенос, а в Horizon действует правило clean-room. Пишем по знанию техник (статьи, общеизвестные алгоритмы).

Пресеты должны оставаться: off (ваниль), on (пост-эффекты мода), hd (этот рендер), позже rt (аппаратная трассировка, отдельно).

Где код

Что Где
Весь HD-конвейер: цели, проходы, WGSL-шейдеры (строками), тайлы света, AO, тени, bloom, tonemap, TAA horizon/crates/horizon-client/src/gfx/hd.rs
Встраивание в кадр: G-буфер-проход, каскады теней, вызовы hd.light / hd.finish, джиттер, тайминги horizon/crates/horizon-client/src/gfx.rs (Renderer::render, ищи hd_on, AirDef fork:)
G-буфер террейна: fs_gbuffer, fs_shadow horizon/crates/horizon-client/src/terrain.wgsl
G-буфер сущностей и моделей мода: fs_entity_gbuffer, fs_entity_shadow horizon/crates/horizon-client/src/entity.wgsl
Пост-проход мода (взрывы, дым, вспышки, свечение) и его прелюдия airdef-mod/shaders/effects.wgsl, прелюдия в horizon/.../gfx/mod_post.rs
Источники света мода (пламя, ракеты, взрывы, прожекторы) airdef-mod/src/lib.rs, fn lights
API мода: render.set-lights, render.set-lighting (уровень API 10) horizon/crates/horizon-mod-sdk/wit/horizon.wit, horizon/crates/horizon-mods/src/runtime.rs

Форк ведётся в horizon/ (ветка airdef), в репозиторий мода попадает патчами:

cd horizon && git add -A crates && git commit -m "..."     # коммит в форке
cd .. && rm -f horizon-patches/*.patch && git -C horizon format-patch -q $(cat HORIZON_COMMIT)..airdef -o ../horizon-patches

tools/airdef.py fork сверяет отпечаток HORIZON_COMMIT + патчей (horizon/.git/airdef-stamp) и пересобирает ветку, если они изменились. После ручной перегенерации патчей у себя обнови отпечаток (см. fork_stamp в tools/airdef.py), иначе следующий airdef.py fork пересоберёт ветку (безопасно: прежняя остаётся в airdef-prev).

Конвейер кадра (HD включён)

Все цели в «масштабированном» разрешении мира (world_post), HDR — Rgba16Float. Глубина камеры — reversed-Z (Depth32Float, 1 = близко, 0 = далеко). Позиции везде относительно камеры (camera-relative), мир — в f64 на CPU.

  1. Каскады теней (2 шт., CASCADES = [40, 176] блоков полуразмера, SHADOW_SIZE = 2048, массив глубины из 2 слоёв). Источник — солнце днём, луна ночью (light_of). Матрицы cascades() привязаны к текселям (тени не «ползут»). Во время прохода буфер глобалов мира подменяется на глобалы каскада (copy-трюк) и потом возвращается. Рисуются секции террейна в коробке дальнего каскада (hd_shadow_visible) и сущности-тенеотбрасыватели (shadow_casters: без оверлеев 4/9/10/40 — 40 это светящиеся модели мода).
  2. G-буфер (свой depth): albedo Rgba8Unorm (a = эмиссия), нормаль Rgba16Float (мировая, из dpdx/dpdy), уровни света Rgba8Unorm (x = небо, y = блоки — сырые координаты лайтмапа /240). Террейн + дальние LOD-тайлы + сущности. Вода/полупрозрачное в G-буфер не попадает (идёт ванильным путём) — см. план.
  3. GTAO (полразрешения, Rg16Float: окклюзия, дистанция) + depth-aware блюр 5×5. 3 среза × 5 шагов, радиус 1.8 блока, шум IGN по кадру. Сила — HdFrame.ambient.w (HORIZON_HD_AO=<число>, 0 = выкл).
  4. Освещение fs_light → lit (HDR): max(небо·ambient.x, блоки·ambient.y)·AO + солнце·N·L·тень + точечные источники × albedo + эмиссия; затем ванильный туман заново, объёмные лучи (14 шагов, Henyey-Greenstein g=0.6), ореолы вокруг источников. Точечные источники — по тайлам 16×16 (tile_lists, буфер tiles: на тайл 4 слова — начало/длина списка для поверхностей и для ореолов, потом индексы; переполнение → «все источники»).
  5. Пост-проход мода lit → fx (effects.wgsl: взрывы, дым, вспышки, свечение; при HD его собственная «подсветка огнём» выключена — свет даёт HD).
  6. TAA (в работе, см. статус) — после пост-прохода мода.
  7. Bloom (prefilter + 6 уровней: 13-tap вниз, tent вверх) и tonemap: до 0.8 как есть (ванильный вид), выше — мягкий roll-off по ярчайшему каналу; лёгкий грейд (+12% насыщенности, мягкая S-кривая).

Bind groups кэшируются и пересоздаются только при resize/смене источника (hd_bind_groups_last_frame() → 0 в установившемся режиме).

Привязки fs_light (group 0)

# Что
0 HdFrame (uniform)
1, 2 цвет и глубина мира (ванильный проход)
3, 4, 5 albedo, нормаль, глубина G-буфера
6 источники света (storage, HdLight: pos+radius, color+intensity)
7 уровни света (небо, блоки)
8, 9 массив карт теней, comparison-сэмплер
10, 11 лайтмап, линейный сэмплер
12 тайлы источников (storage)
13 AO

HdFrame (Rust и WGSL держать в синхроне!): inverse_view_proj, resolution (w, h, 1/w, 1/h), params (число источников, экспозиция, bloom, счётчик кадров), cascades[2], sun (направление, сила), sun_color (rgb, ночь), fog_color, fog, ambient (тень неба, блоки, плотность воздуха, AO), shadow (вкл, R0, R1, тайлов в строке).

Как проверять

cd horizon && cargo build --profile fast -p horizon-client --features mods   # без предупреждений
cargo fmt -p horizon-client
cargo test -p horizon-client --lib hd        # naga-разбор всех HD-шейдеров + тест тайлов
cd ../airdef-mod && cargo horizon-mod build && cargo test                    # мод и его шейдер

WGSL-ошибки в hd.rs всплывают только в рантайме — поэтому каждый новый шейдер добавляй в naga-тест lighting_shader_parses.

Игра офскрин (только одна копия за раз; данные в run-home/, мир Polygon):

cd run-home && HORIZON_HOME=$PWD HORIZON_NO_AUDIO=1 ../horizon/target/fast/horizon-ctl --socket $PWD/ctl.sock \
  launch --world Polygon --offscreen --wait --game ../horizon/target/fast/horizon-client \
  --resources "$(ls -d "$HOME/Library/Application Support/horizon-launcher/versions"/*/.local/horizon-client/26.3 | sort -V | tail -1)"
H="../horizon/target/fast/horizon-ctl --socket $PWD/ctl.sock"
$H command "time set 4500"; $H command "tp @s 40 76 40 135 25"   # полигон с техникой; z ≥ 60 — море
# команды мода — через чат: $H key t tap; $H type "/airdef shader hd"; $H key return tap
$H key f1 tap; $H screenshot out.png; $H bench 4; $H quit

Тайминги проходов на GPU: HORIZON_SHADER_PACK_TIMING=1 (лог в run-home/ctl.log) или список F3. Ориентиры (M5, 2560×1440, до оптимизации теней): тени 1.3 + 5.4 мс, G-буфер 0.8, AO 2.9, освещение 5.2, bloom 1.1, tonemap 0.2 — кадр ≈ 17 мс GPU.

Отладка: временно выводи промежуточные величины цветом в fs_light (так нашли пустую карту теней и неверное направление солнца). Помни: солнце в мире идёт по оси X ((-sin a, cos a, 0)), а Globals.sun неба — в своей плоскости YZ.

Статус

Этап Состояние Коммит
1. G-буфер, точечный свет мода в HDR, bloom, тон-кривая; API set-lights/set-lighting готово 0a56f56 (форк)
2. Тени солнца/луны, переосвещение мира, лучи, ореолы, туман, грейд готово патч 12
Кэш bind groups, тени только от тенеотбрасывателей (#12, #13) готово патч 13
Тайловые списки источников (#10) готово патч 14
Тайминги HD-проходов (#9), GTAO готово патч 15, ed2db85
Отсечение взрывов в effects.wgsl (#11), порядок дыма (#16), метрика перекрытия свечения (#14) готово 67a2a52, ed2db85
Удешевление дальнего каскада теней в работе —
TAA (джиттер Halton 2,3, перепроекция по глубине, клиппинг в YCoCg) в работе —

План (по порядку) и ТЗ

Каждый пункт — самостоятельная задача. Перед началом прочитай hd.rs целиком.

  1. TAAU — временной апскейлер (поверх TAA). Мир и G-буфер рендерятся в render_scale (например 0.67), TAA-проход восстанавливает полное разрешение: история в полном разрешении, текущий кадр семплируется с учётом джиттера (Catmull-Rom/Lanczos-веса по субпиксельной позиции), клиппинг окрестности как в TAA. Настройка масштаба (HORIZON_HD_SCALE или поле в HdSettings). Цель: при 0.67 картинка близка к нативной, FPS заметно выше. Альтернатива на Mac — MetalFX через wgpu-hal (нативный код, только Metal) — отдельной опцией потом. DLSS нереален для нашей цели (только NVIDIA через Streamline, нет в wgpu).
  2. Вода: отдельный G-буфер-путь для воды (маска + нормаль с анимированными волнами), SSR (трассировка по глубине, откат на небо/туман), преломление (смещение по нормали), затухание по глубине воды (цвет биома), блики солнца (GGX-подобный), френель. Подводный вид не ломать (frame.underwater).
  3. Небо и атмосфера: рассеяние Рэлея/Ми (предвычисленная LUT пропускания и небесного цвета в маленькой текстуре), солнце/луна дисками, звёзды из ванили; туман и лучи берут цвет из той же модели. Учесть дождь (weather), закат, Незер/Энд (там — ванильное небо).
  4. Объёмные облака (рэймарч слоя с шумом) + их тени на земле (в карту/маску солнца).
  5. Блики и материалы: specular солнца для металла техники (маска по оверлею/альбедо или атрибут модели из мода), мокрые поверхности и лужи в дождь.
  6. PCSS (мягкость тени по расстоянию до тенеотбрасывателя) и цветные тени через стекло/листву.
  7. Ветер листвы/травы (вершинный шейдер террейна по типу блока), рябь от дождя.
  8. Объёмный дым пожаров и взрывов, принимающий свет и тени (сейчас дым — в effects.wgsl, без теней).
  9. Опционально: motion blur, DoF (для кинокамеры повторов).
  10. RT-пресет: wgpu EXPERIMENTAL_RAY_QUERY (Vulkan/DX12/Metal M3+), BLAS по секциям, ray-query тени и отражения, затем GI. Отдельный пресет, HD остаётся.

Правила

  • Ничего не ломать в off/on; HD выключен — код HD не работает вовсе (hd = None).
  • Без потери качества ради скорости без договорённости (шаги, разрешение, число эффектов).
  • Каждый новый WGSL — в naga-тест. Каждый новый проход — в тайминги (PassTiming).
  • Комментарии — короткие предложения о том «зачем»; в gfx.rs префикс AirDef fork:.
  • Коммиты: в форке, затем патчи; подпись Co-Authored-By: Claude <модель> <noreply@anthropic.com>.
  • Пуш в Gitea с машины без DNS: ssh://git@100.92.6.40:2222/chexit/airdef.git (ключ ~/Documents/claude-keys/deploy).
  • Обнови этот документ (статус + что изменилось в конвейере) в том же коммите, что и код.