diff options
| author | Valentin Popov <valentin@popov.link> | 2026-10-11 20:41:37 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-10-11 20:41:37 +0300 |
| commit | c90ec80dc0cc90e76b78f84d98d1ac9c5f02c4eb (patch) | |
| tree | 727a76e3c32e0c6b94a2294bc29673fa2c1174b3 /docs | |
| parent | bfe4db16114d415475451ae49557c45833c0541e (diff) | |
| download | fparkan-c90ec80dc0cc90e76b78f84d98d1ac9c5f02c4eb.tar.xz fparkan-c90ec80dc0cc90e76b78f84d98d1ac9c5f02c4eb.zip | |
Fix material categories and transparent background ordering
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/reference/materials.md | 17 | ||||
| -rw-r--r-- | docs/reference/render-frame.md | 41 | ||||
| -rw-r--r-- | docs/tomes/06-behavior.md | 17 |
3 files changed, 64 insertions, 11 deletions
diff --git a/docs/reference/materials.md b/docs/reference/materials.md index bfeccf4..c148bc8 100644 --- a/docs/reference/materials.md +++ b/docs/reference/materials.md @@ -57,10 +57,12 @@ struct Phase34 { ### Pipeline category -Call site извлекает native category как `(attr1 >> 2) & 0xF` и передаёт её в -`LegacyPipelineState::with_material_category`. Таблица содержит пять -подтверждённых категорий; helper возвращает `None` для остальных значений и не -меняет уже выбранные depth и cull state. +Call site извлекает native category как `(attr1 >> 2) & 0xF` и сохраняет её на +разрешённом phase material. World draw ranges получают состояние для начального +selector при подготовке, а animated selector обновляет category вместе с +material selector. Fixed environment ranges keep their authored pipeline state. +Таблица содержит пять подтверждённых категорий; helper возвращает `None` для +остальных значений и не меняет уже выбранные depth и cull state. | category | source/destination colour factors | alpha test | | ---: | --- | --- | @@ -75,6 +77,13 @@ material category. Alpha reference remains draw-range data, while the Vulkan pipeline key includes the blend mode, depth mode, cull mode and alpha-test variant so ranges with different native state do not share a pipeline. +World transparency is a separate draw-queue decision. A world range joins that +queue when sampled diffuse opacity is below one or any bit in the native +`0x108` batch-flag mask is set; the MAT0 category alone does not make it +transparent. A queued range +with a depth attachment tests depth without writing it. Unsupported categories +fail world-range setup instead of silently falling back to opaque state. + Каждая phase занимает 34 байта: 18 parameter bytes и 16-byte C string имени текстуры. Loader переводит параметры в коэффициенты так: diff --git a/docs/reference/render-frame.md b/docs/reference/render-frame.md index 2c356dc..015f9f3 100644 --- a/docs/reference/render-frame.md +++ b/docs/reference/render-frame.md @@ -40,6 +40,47 @@ end-of-render. Подготовленный item должен ссылаться на immutable данные кадра. Изменение phase или texture cache посреди прохода не должно менять уже собранную очередь. +## MAT0 state and transparent backgrounds + +For mission world ranges, the selected MAT0 material supplies its native +pipeline category. The category sets blend and alpha-test state while preserving +the range's depth and cull state; an animated material selector updates the +category with the selector. Queue membership is independent: sampled opacity +below one or native batch flags `0x108` mark a world range transparent, and a +queued range with depth enabled tests depth without writing it. Fixed +environment ranges keep their explicit states. + +The fixed-camera preview explicitly marks nebula/stars, dome and cloud ranges as +transparent backgrounds. Opaque world ranges stay in their world slots; the +transparent world queue is sorted back-to-front and inserted immediately after +the last marked background. Other fixed ranges retain their relative order. +Thus cloud layers can be drawn before transparent foliage, while later sun, +weather and other foreground ranges keep their existing relative order. This +is a narrow queue rule, not a reordering of every sky or effects pass. + +## Regression evidence + +`cargo test -p fparkan-render-vulkan --lib material_category_and_transparency_preserve_world_state_in_either_order --offline` +checks that category 1 remains source-alpha with alpha testing, retains depth +and cull settings in either update order, and rejects unsupported categories. +`cargo test -p fparkan-render-vulkan --lib tree_canopy_queue_follows_sky_and_precedes_foreground_effects --offline` +checks the explicit queue order: screen gradient, opaque terrain/building, +shadow, nebula/dome/clouds, far-to-near transparent canopy, then sun/weather. + +Viewer-only paired readbacks used `--frames 3 --validation +--legacy-camera-capture` with the pre-fix and patched builds. On AutoDemo TMA +object 4 (`wor_l_n1.dat`, `fr_l_plant`), the 1280x720 camera at eye +`[464.319, 904.719, 38.0]`, aimed at `[374.319, 814.719, 12.0]` with FOV +`0.62`, changed the two black facade panels to tinted, textured portal +surfaces. On Mission.01 object 12 (`s_tree_04`), the 1280x1024 camera at eye +`[492.63855, 312.90244, 46.5]` aimed at +`[492.63855, 442.90244, 55.0]` crosses the canopy against open sky; paired +three-frame captures at the same synthetic atmosphere phase (600 seconds) show +the patched build restoring the missing upper/right fronds along that sky +boundary. Both runs reported clean Vulkan validation. These captures verify our +preview behavior and do not prove the native renderer's pass order, portal +transmittance or exact color. + ## GOG camera dispatch evidence For the GOG `World3D.dll` baseline with SHA-256 diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md index a3fa711..8b5b09f 100644 --- a/docs/tomes/06-behavior.md +++ b/docs/tomes/06-behavior.md @@ -275,14 +275,17 @@ buffers и передаёт собранную settings-структуру даÐ `ret 0x0c`; `CreateCollManager` и `CreateCollObject` возвращают interface pointer с поправкой `+4` после внутренней инициализации. -Headless Ghidra 12.1.2 decompile GOG binary подтверждает ABI формой экспортов -`LoadControlSystem(char*, char*, char*, char*, char*, u32, void*, i32)`, +Инструкциям x86 в GOG `Control.dll` (`+0x32280`) и caller-у в `AniMesh.dll` +(`+0x32e7`) соответствует ABI `LoadControlSystem(char*, char*, char*, char*, +char*, char*, void*, i32)`: шесть C-string pointers, resource context и mode. +Функция заканчивается `ret 0x20`, то есть снимает все восемь 32-bit stack +arguments; arg7 передаётся constructor-у как context, arg8 выбирает mode. +Прежняя декомпиляция ошибочно определяла шестой строковый аргумент как `u32`. +Остальные exports имеют формы `LoadPhysicalModel(u32, u32, u32)`, `CreateCollManager(u32)` и -`CreateCollObject(u32, u32)`. Первые пять параметров Control loader — строки, -а mode передаётся последним; decompiler не восстанавливает предметные имена -остальных слов. `InitializeSettings` получает `CreateGameSettings()` из -World3D и делает virtual call slot `+0x24` с literal `0x15` и строкой по RVA -`0x42478`. +`CreateCollObject(u32, u32)`. `InitializeSettings` получает +`CreateGameSettings()` из World3D и делает virtual call slot `+0x24` с literal +`0x15` и строкой по RVA `0x42478`. Именно update methods этих private objects, а не пять exports, остаются следующим объектом динамической трассировки. Поэтому reference movement в |
