aboutsummaryrefslogtreecommitdiff
path: root/docs/tomes/05-render.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tomes/05-render.md')
-rw-r--r--docs/tomes/05-render.md68
1 files changed, 68 insertions, 0 deletions
diff --git a/docs/tomes/05-render.md b/docs/tomes/05-render.md
index cfd352a..53667c8 100644
--- a/docs/tomes/05-render.md
+++ b/docs/tomes/05-render.md
@@ -1138,6 +1138,74 @@ lightmap state передаются в `VulkanStaticMaterial`, а shader посÐ
сэмплирует эти четыре стадии. Animation clock обновляет выбранные фазы и
коэффициенты без пересборки terrain mesh, сохраняя native type-14 overlay mask.
+### Отражение на воде
+
+Поверхность воды нельзя рисовать тем же умножением текстур, что и землю.
+В проходе ландшафта GOG Terrain.dll флаг грани `0x20000` участвует в выборе
+отражения; при включённом EMBM живой водный кадр использует texture mode 10.
+Оригинал создаёт для этого отдельную камеру `REFLECTION_SHIFTED`.
+В [эталонной сборке](../reference/original-binaries.md) выбор грани находится
+в Terrain.dll RVA `0x28A50`, а подготовка EMBM-пакета — в RVA `0x1B540`.
+
+Для горизонтальной воды на высоте `h` камера отражения находится в точке
+`[eye_x, eye_y, 2h − eye_z]`. Но она не повторяет наклон основной камеры:
+смотрит вертикально вверх, а её окно лежит на прямоугольнике водоёма. Поэтому
+текстура отражения привязана к местности, а не к экрану игрока. В плоскости
+воды координаты изображения равны `U = 1 − Ynorm`, `V = 1 − Xnorm`.
+
+Terrain.dll RVA `0x4EFF0` передаёт shifted-проекции пять значений:
+`[min_y − eye_y, min_x − eye_x, span_y, span_x, eye_z − h]`. Например,
+для наблюдателя `[1200, 800, 185]`, воды `150` и границ
+`[1000, 500, 1500, 1200]` это `[-300, -200, 700, 500, 35]`.
+Матрица камеры и эти аргументы проверены исполнением оригинальной функции
+при двух положениях и разных поворотах основной камеры. Оракул подменяет
+ввод-вывод очереди, ландшафта и камеры; сам renderer и матрица глубины в эту
+проверку не входят. Vulkan-проекция сохраняет near/far основного вида;
+Rust-тест отдельно проверяет углы водоёма и границы глубины.
+
+Отражённый вид меняет сторону отсечения и отбрасывает геометрию ниже воды.
+Небо и оставшаяся сцена попадают в отдельную цветовую текстуру с собственной
+глубиной. В основном проходе водные треугольники читают её по координатам
+водоёма с добавленным смещением волн. Для неперспективной камеры API остаётся
+обычное зеркало с экранными координатами.
+
+Цветовой target переходит из attachment layout в shader-read layout после
+записи. Следующий зеркальный проход ждёт предыдущего чтения этой текстуры;
+основной и отражённый виды используют разные слоты uniform buffer. Во время
+записи отражения привязан отдельный нейтральный descriptor, чтобы проход
+не читал собственное вложение.
+
+Волны не требуют готовой текстуры из ресурсов: Terrain.dll RVA `0x2BF50`
+создаёт карту 128×128 со знаковыми парами Du/Dv. Для нормированных координат
+текселя `x` и `y` угол равен `(x + y − 1) × 12,566360473632812`, а компоненты —
+округлённые `64 cos(угол)` и `64 sin(угол)`. Все 32 768 байт Rust-генератора
+сверены с исполнением этой функции DLL при игровом x87 CW `0x007F`.
+
+Рябь привязана к водоёму, поэтому не плывёт вслед за экраном. Конструктор
+ландшафта собирает прямоугольник всех отражающих граней; U меняется против
+мировой Y, V — против X. Эти координаты повторяются сто раз, к обеим прибавляется
+`(queue_clock % 10000) / 10000`. Это самостоятельный clock: время суток и
+относительный clock неба не задают фазу волн. Захват хранит исходный
+`sky_uv_clock.raw_clock`; ограниченный replay фиксирует его, интерактивный
+продолжает с этого значения. Старые захваты без raw clock явно считаются в
+`captured_water_phase_unverified`.
+
+Карта Du/Dv смещает координаты следующей текстуры с диагональными коэффициентами
+`0,01`, без изменения яркости. Это правило
+[Direct3D BUMPENVMAP](https://learn.microsoft.com/en-us/windows/win32/direct3d9/bump-mapping-formulas).
+В Vulkan карта хранится в двух каналах несжатой текстуры и возвращается к
+знаковым значениям перед вычислением смещения.
+
+Матрица положения камеры, её окно и координаты волн восстановлены, но весь
+контекст отражённого вида ещё не повторён. Диапазон глубины, небо, туман и FX
+заимствуются из основного вида, а размер target совпадает со swapchain.
+Эти ограничения учитываются в `planar_reflection_render_context_approx`;
+совпадение генератора волн и окна не доказывает совпадения итогового отражения.
+Один target обслуживает ближайшую
+активную высоту воды; другие высоты и негоризонтальные поверхности явно
+считаются как неподдержанные. Это промежуточный водный проход, а не полная
+приёмка воды или лавы.
+
## Реализация Vulkan
`LegacyPipelineState` хранит blend, depth, cull и alpha-test. Из этих значений