fix: align native MSH face culling
Docs Deploy / Build and Deploy MkDocs (push) Successful in 31s

This commit is contained in:
Valentin Popov committed 2026-10-18 07:33:56 +04:00
1 parent c77c078efe
commit 0c6e7589f9
2 files changed
+432 -11

No files matched your search

+47
View File
@@ -153,3 +153,50 @@ Byte `material_index` выбирает строку WEAR; high word at `+0x02`
`index_start + index_count` остаётся внутри type 6, а каждый использованный
индекс через `base_vertex` попадает в position stream. `vertex_count` и
`local_batch_index` доступны renderer для исходного draw contract.
## Сторона грани в цветовом проходе
В цветном проходе `Terrain.dll`, функция `0x100296F0`, сравнивает камеру с
каждой гранью по знаку тройного произведения:
```c
d = dot(eye - v0, cross(v1 - v0, v2 - v0));
```
Проход оставляет грань только при `d > 0`. Raw `Batch20.flags` задаёт два
исключения: `0x0002` пропускает программную проверку стороны, поэтому обратная
грань не отбрасывается этим условием. С `0x4000` проверяется только первая
грань записи: если `d <= 0`, цикл её граней прекращается; если `d > 0`,
оставшиеся грани этой записи уже не проходят повторную программную проверку.
`Terrain.dll!0x100296F0` также настраивает пакет этого цветного пути: flags по
адресу `packet+0x128` равны `0x404` или `0x414`. Путь отправки в
`Terrain.dll!0x1001D660` перед вызовом renderer vtable `+0x48` очищает только
маску `0x1`; `Ngi32.dll!0x10007470` проверяет маску `0x4` этого аргумента. При
установленной маске render state 22 получает `D3DCULL_NONE`, иначе —
`D3DCULL_CW`. Оба значения CShade сохраняют маску `0x4`, поэтому в этом
цветном пути аппаратное отсечение выключено, а набор обычных граней определяет
программный тест `d > 0`. Raw-флаги `0x0002` и `0x4000` меняют этот тест, как
описано выше.
Статический Vulkan preview сохраняет каждую исходную запись `Batch20` одним
диапазоном рисования:
`append_static_preview_component_with_lightmaps` добавляет исходные индексы без
перестановки, а в диапазон переносит `index_count` и исходный `first_index` с
общим смещением компонента. Поэтому `0x4000` выбирает ту же первую грань, даже
если диапазон получил другой материал для lightmap.
Поскольку вершины preview переведены в мировые координаты, знак `d` для MSH
диапазона корректируется знаком детерминанта полной матрицы размещения. Повороты
узлов и mounts — единичные кватернионы с determinant `+1`; отрицательный object
scale меняет знак. Renderer Vulkan задаёт `front_face=CLOCKWISE` и viewport с
положительной высотой. Для используемых матриц legacy и free-flight preview
при положительном determinant native-visible `d > 0` относится к Vulkan
back-face; поэтому preview отсекает `FrontFace`. При отрицательном determinant
режим меняется на `BackFace`.
Для `0x0002` и `0x4000` аппаратное отсечение выключено, чтобы сохранить их
программную политику. Отклонённый `0x4000` диапазон получает число индексов 0;
каждый кадр это число заново вычисляется из исходного значения, поэтому после
изменения положения камеры или opacity материала диапазон может вернуться в
draw queue. Проверка первой грани
применяется только к MSH-диапазонам цветовой мировой очереди; terrain и
shadow/sun запросы её не используют.