V02. Деревья и импостеры по кромке 10 м, ровный тон с высоты (VR-21, VR-6)

Цель: модели и импостеры стоят ровно по кромке леса из маски 10 м, опушка читается стеной деревьев; на 2 км импостеры не темнее полога и без ступеньки яркости на границе 3,5 км.

Контекст: docs/guide/terrain.md («Лес с высоты — три плана»), docs/guide/vegetation.md (V01), scripts/terrain/tree_placer.gd, forest_impostors.gd/.gdshader, terrain_tree_models.gd, API Terrain.get_forest_mask() из T02. Владения: scripts/terrain/{tree_placer.gd, terrain_tree_models.gd, tree_model.gdshader, forest_impostors.gd, forest_impostors.gdshader, terrain_trees.gd, trees.gdshader}, configs/vegetation.json (trees), tests/vegetation/, docs/guide/vegetation.md. Не трогать: terrain.gd (вызов set_forest_mask уже добавлен T02), terrain.gdshader.

Шаги

  1. set_forest_mask(image, origin, cell_m) у TerrainTreeModels и ForestImpostors; дерево ставить при доле леса ≥ 0,5 по маске 10 м (вместо класса 25 м), ближе к кромке — гуще и крупнее (опушечные деревья), утопление edge_sink_fraction.
  2. Импостеры: освещение и средний тон атласа согласовать с пологом T02 (средняя яркость на расстоянии перехода); плавное растворение у outer_m без полосы.
  3. Проверить тени импостеров/моделей на лугу у опушки (не должно быть тёмного ореола от теней шире реальной высоты крон).

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

  • Тест: ≥ 98 % деревьев (модели + импостеры) при доле леса ≥ 0,5; ни одного центра дальше 5 м в луг; просеки соблюдаются.
  • S3: линия стволов/крон совпадает с кромкой полога ±10 м (профиль compare_ref.py), провал яркости луга у кромки ≤ 8 %.
  • S5: скачок средней яркости леса на границе импостеры/полог ≤ 5 %; отношение лес/луг в ±20 % от фото (a).
  • GPU деревьев (S1, S3: полный − --no-trees) — не выше базы T01.

Зависимости: T02 (маска и API). Параллельно с T03, T04. Модель: opus. Размер: M.