Fix material categories and transparent background ordering
Docs Deploy / Build and Deploy MkDocs (push) Successful in 40s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 40s
This commit is contained in:
@@ -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 переводит параметры в коэффициенты так:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 в
|
||||
|
||||
Reference in New Issue
Block a user