[bug] HD water: прозрачные объекты перед водой отключают её композит и попадают в преломление #36

Closed
opened 2026-10-29 16:21:47 +00:00 by chexit · 1 comment
Owner

🤖 Filed by Codex, AI-агент Владимира (chexit).

Проверено на f443f0a. Источник: патч 19, gfx/hd.rs: fs_light, WATER::fs_water, water_composite; также порядок проходов в gfx.rs.

Два проявления одной проблемы: вода композится после прозрачностей, но не имеет чистого цвета сцены позади воды и согласованной с этим цветом глубины.

1. Прозрачный фрагмент переключает всю воду под ним на vanilla-путь

fs_light ставит маску воды, только если d - wd <= d * 0.002. Основная глубина d уже содержит стекло и прозрачные частицы (соответствующие terrain/entity pipelines пишут глубину), даже когда их альфа мала.

CPU-проверка условия:

water wd = 0.005; opaque floor g = 0.0025
d = 0.005 (только вода)          -> water = true
d = 0.010 (частица перед водой)  -> water = false

Во втором случае lit.a=1, а fs_water немедленно возвращает base.rgb. Под полупрозрачной частицей сохраняется vanilla-вода, тогда как вокруг неё идут HD-волны/отражения. Альфа частицы в выборе этой ветки вообще не участвует.

2. Преломление проверяет непрозрачную глубину, а читает цвет с передними прозрачностями

В fs_water смещённая выборка принимается по gbuffer_depth: z > 0 && z <= wd. Затем цвет берётся из lit_tex, где уже может быть объект перед водой.

Пример валидных reversed-Z входов: wd=0.005, глубина непрозрачного дна соседнего пикселя z=0.0016667, но итоговая глубина этого пикселя d=0.01 из-за стекла/частицы. Проверка принимает соседний пиксель как «за водой», а цвет фактически содержит переднее стекло/частицу. Оно начинает растягиваться/преломляться в воде, хотя находится перед ней. При билинейной выборке нужно учитывать и соседние texels.

Подтверждено анализом буферов и числовой проверкой веток; GPU-сцену здесь не запускали.

Что изменить

Согласовать порядок и данные: например, освещение непрозрачной сцены → вода с преломлением этого цвета → прозрачные объекты перед водой; для объектов под водой сохранить корректную глубину/композицию. Альтернатива — отдельный background color/depth для воды и явные маски прозрачностей. Отбраковка по глубине должна проверять тот слой, откуда взят цвет.

Приёмка

На берегу, над водой: цветное стекло перед камерой и полупрозрачные частицы, затем те же объекты под водой. Передние объекты должны накладываться поверх одинаковой HD-воды без прямоугольных участков vanilla-воды и без затягивания в преломление. Проверить также scale=0.67 и кромку стекла/берега.

🤖 Filed by Codex, AI-агент Владимира (chexit). Проверено на `f443f0a`. Источник: [патч 19](https://gitea.maoniao.team/chexit/airdef/src/commit/f443f0a94a71eb2d446792f1829146f9563aaf5d/horizon-patches/0019-HD-water-its-own-pass-colour-normal-depth-the-floor-.patch), `gfx/hd.rs`: `fs_light`, `WATER::fs_water`, `water_composite`; также порядок проходов в `gfx.rs`. Два проявления одной проблемы: вода композится после прозрачностей, но не имеет чистого цвета сцены позади воды и согласованной с этим цветом глубины. ### 1. Прозрачный фрагмент переключает всю воду под ним на vanilla-путь `fs_light` ставит маску воды, только если `d - wd <= d * 0.002`. Основная глубина `d` уже содержит стекло и прозрачные частицы (соответствующие terrain/entity pipelines пишут глубину), даже когда их альфа мала. CPU-проверка условия: ```text water wd = 0.005; opaque floor g = 0.0025 d = 0.005 (только вода) -> water = true d = 0.010 (частица перед водой) -> water = false ``` Во втором случае `lit.a=1`, а `fs_water` немедленно возвращает `base.rgb`. Под полупрозрачной частицей сохраняется vanilla-вода, тогда как вокруг неё идут HD-волны/отражения. Альфа частицы в выборе этой ветки вообще не участвует. ### 2. Преломление проверяет непрозрачную глубину, а читает цвет с передними прозрачностями В `fs_water` смещённая выборка принимается по `gbuffer_depth`: `z > 0 && z <= wd`. Затем цвет берётся из `lit_tex`, где уже может быть объект **перед** водой. Пример валидных reversed-Z входов: `wd=0.005`, глубина непрозрачного дна соседнего пикселя `z=0.0016667`, но итоговая глубина этого пикселя `d=0.01` из-за стекла/частицы. Проверка принимает соседний пиксель как «за водой», а цвет фактически содержит переднее стекло/частицу. Оно начинает растягиваться/преломляться в воде, хотя находится перед ней. При билинейной выборке нужно учитывать и соседние texels. Подтверждено анализом буферов и числовой проверкой веток; GPU-сцену здесь не запускали. ### Что изменить Согласовать порядок и данные: например, освещение непрозрачной сцены → вода с преломлением этого цвета → прозрачные объекты перед водой; для объектов под водой сохранить корректную глубину/композицию. Альтернатива — отдельный background color/depth для воды и явные маски прозрачностей. Отбраковка по глубине должна проверять тот слой, откуда взят цвет. ### Приёмка На берегу, над водой: цветное стекло перед камерой и полупрозрачные частицы, затем те же объекты под водой. Передние объекты должны накладываться поверх одинаковой HD-воды без прямоугольных участков vanilla-воды и без затягивания в преломление. Проверить также scale=0.67 и кромку стекла/берега.
chexit added the priority:P2area:renderingtype:bug labels 2026-10-29 16:21:47 +00:00
Author
Owner

🤖 Agent: сделано в https://gitea.maoniao.team/chexit/airdef/commit/e3148bf (запушено в main).

🤖 Agent: сделано в https://gitea.maoniao.team/chexit/airdef/commit/e3148bf (запушено в main).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: chexit/airdef#36