Use raw world-space terrain heights throughout mesh, camera-floor, shadow, and sun-ray paths while preserving the projection far-plane conversion. Complete the verified selected-camera readback flow with frozen phase sampling, capture tooling, and documentation.
6.4 KiB
Render frame
Кадр является последней стадией цикла, а не самостоятельной функцией renderer-а. До draw calls уже накоплен input, рассчитан tick, применены отложенные операции, выбрана камера и обновлён 3D sound listener.
Frame skeleton
system messages and input
-> simulation calculation
-> deferred object operations
-> animation and transforms
-> camera and sound listener
-> visibility and render queues
-> materials and draw passes
-> renderer completion
-> end-of-render callbacks and UI
В World3D::stdRenderGame доказан крупный порядок: camera передаётся Terrain,
настраиваются viewport/matrices, вызываются renderer boundary slots,
устанавливается in_render, выполняется traversal мира, закрывается world/shade
pass, вызывается renderer completion, снимается in_render, рассылается
end-of-render.
Draw item
Подготовленный draw item содержит:
- node world matrix;
- batch flags and index range;
- WEAR material handle;
- MAT0 active phase and coefficients;
- texture handle;
- optional lightmap handle;
- render phase and sorting key;
- legacy pipeline state.
Подготовленный item должен ссылаться на immutable данные кадра. Изменение phase или texture cache посреди прохода не должно менять уже собранную очередь.
GOG camera dispatch evidence
For the GOG World3D.dll baseline with SHA-256
17e4a3089b2583a8cf2356c9db0390b1aba138356a09130d79b4e7e4791da61e,
the exported stdRenderGame is RVA 0x13BD0. It first calls
Terrain::stdSetCurrentCamera2(camera), stores the camera pointer only for
the frame, and clears it before return. sendEndOfRender is a separate export
at RVA 0x13D90. This is frame-order evidence only: the camera ABI, matrices
and viewport values are not recovered by this call-order analysis. The
implemented preview path below accepts selector-0 input produced through the
native frame capture workflow.
The capture workflow also records an observed mission path and, when
its thread/generation and clock checks succeed, an atmosphere_seconds sample.
For a fixed-camera preview, the renderer uses that optional absolute schedule
phase when no --atmosphere-seconds override is supplied and keeps schedule
sampling at that exact phase across readback frames. An explicit CLI value takes
precedence. The phase sample is not full simulation time: weather, RNG, and
other mission state remain unknown, so this evidence does not establish
full-frame parity.
Receiver-side GOG Terrain evidence refines this contract. stdSetCurrentCamera2
(RVA 0x4FD40 in Terrain SHA-256
af87d1b2e728a0be73c52be3b44cc196ab46da7799f25a15d40f8c9b0b425ead) queries
selector 18 on the supplied object and invokes slot +12 on that result. It
does not store the supplied pointer in stdGetCurrentCamera2; that getter
returns a Terrain global populated by selector 8 during Terrain initialization.
Terrain.dll!LoadCamera adds a separate factory-side contract. Its GOG entry
at RVA 0x4EBE0 is __stdcall with four machine-word arguments, allocates
0x1A4 bytes, calls the constructor at RVA 0x4EC60, and returns the interface
at object offset +0x134. The constructor passes arguments 3 and 4 into base
initialization at this + 4, writes argument 3 to this + 0x138, and calls a
helper at RVA 0x4CEF0 with arguments 1, 2 and 4 plus this. Argument 1 is a
mode string: only REFLECTION and REFLECTION_SHIFTED produce a non-zero mode
value at this + 0x1A0. This is factory ABI evidence, not a recovered view or
projection matrix contract.
Legacy camera preview path
fparkan-game --legacy-camera-capture <json> consumes the selector-0 transform,
the native D3D7 viewport RECT [left, top, right, bottom], near/far planes and
field of view. It derives the D3D7 view and clip transform from those inputs,
carries the resulting clip_from_world matrix into the preview camera, and
keeps the view-matrix camera axes directly, so the captured basis, including
roll, is not reduced to yaw/pitch. The RECT becomes a physical drawable extent
of right - left by bottom - top. The preview window is fixed to that extent;
startup and non-zero resize events reject a physical-size mismatch instead of
stretching the captured view. Compare the result with the corresponding
[left, top, right, bottom] crop of the original PNG. FreeFlightCamera is not
created in this mode, but redraws still update environment and projected
shadows from the captured camera. Before environment updates can emit sound
events, the audio listener receives the captured position, forward and up axes;
initial world draw sorting uses the same captured position. A phase capture may
include an observed mission path and a verified atmosphere_seconds value; the
latter is used only when no explicit CLI override is supplied. This value pins
the atmosphere schedule sample during a fixed-camera comparison while FX still
receives real frame time. simulation_time_seconds, weather, RNG and complete
mission state remain unknown, and a camera/phase match alone does not establish
visual parity with a native frame.
Parity risks
VulkanStaticCamera::from_legacy_d3d7 keeps the D3D7 view and projection
reconstruction in fparkan-render, then negates the vertical projection term
once at the Vulkan adapter boundary. D3D7's top-down viewport places positive
NDC Y at the top; the Vulkan swapchain uses a positive viewport height, so the
adapter flips NDC Y while the shader preserves gl_Position. The generic
from_row_major_view_projection path remains unchanged; its callers supply
Vulkan-ready matrices, as the free-flight camera already does.
- x87 precision and rounding;
- scalar/SIMD
g_FastProcdifferences; - object, batch and transparent primitive order;
- depth, cull, alpha test and blend transitions;
- mip-skip, palette and Page coordinates;
- material fallback and phase selection;
- RNG sequence for FX and atmosphere;
- device capability fallback;
- simulation time quantization.
Для отладки нужен deterministic frame capture: camera state, visible object IDs, draw-item list, pipeline keys, matrices и hashes промежуточных buffers.