T04. Дымка и дальний контраст по реальным фото

Цель: дымка синит и смягчает даль как на фото, но не «съедает» контраст на 2–10 км; верх дымки на инверсии остаётся резким (VR-3, FR-20).

Контекст: docs/guide/terrain.md («Мир», «Дымка и инверсия»), scripts/world/haze.gdshader, scripts/world/sky_environment.gd, configs/world.json (fog, haze, sky, effects), фото (c) и metrics.json T01. Владения: scripts/world/, configs/world.json (разделы fog, haze, sky, effects), tests/terrain/test_haze.gd (новый). Не трогать: docs/guide/terrain.md (в этой волне правит T03) — абзац об изменениях дымки приложить к отчёту.

Шаги

  1. Разобрать сложение голубого тумана Godot и haze.gdshader (двойное ослабление?) — цена контраста по дальности: 1, 5, 10, 20, 50 км.
  2. Подогнать: видимость, долю in-scatter против ослабления, aerial_perspective, max_opacity, цвет у солнца/против солнца, чтобы кривая «контраст vs дальность» в S5 шла как на фото (c).
  3. Сохранить: верх слоя = set_inversion_height_msl(h) + margin, резкий край сверху; видимость ≥ 20 км (FR-20).
  4. Тест test_haze.gd: оптическая толщина по лучу — аналитика против численного интеграла (≤ 1 %), пропускание на 20 км ≥ 20 %.

Критерий приёмки (стенд T01)

  • S5: отношение RMS-контраста «средне/близко» и «далеко/близко» — в ±25 % от фото (c); монтаж S5|c в отчёте.
  • S5: хребет на ≥ 20 км отличим от неба (контраст ≥ 3 %) и синее ближнего (B/R выше ≥ 10 %).
  • Кадр с 2500 м над инверсией 1900 м: граница дымки у горизонта — переход ≤ 12 пикселей.
  • GPU полного кадра S5 — не выше базы + 0,05 мс; тесты tests/terrain зелёные.

Зависимости: T01; параллельно с T03. Модель: opus. Размер: S.