Phase 3b: live OpenGL render backend in DOSBox-X (VPX_RENDER=1)

The emulated VPX board now draws frames in real time. The FIFO burst
assembler feeds an in-process DPL scene store; each vr_draw_scene publishes a
frame snapshot to a dedicated WGL window thread that renders it fixed-function.

- vpxlog.cpp: scene_burst() decode + VScene store + rt_main GL window thread;
  glFrustum from the view-node window rect, glScalef(-1,1,1) for Division's
  mirrored screen-x, action-31 camera as modelview. No build change (opengl32
  already linked).
- Validated: flyk divrgb.scn opens the "VPX VelociRender (emulated)" window
  and draws the SMPTE bars live via the real camera.spl spline camera
  (divrgb-live-gl.png), matching the offline render_capture.py decode.
- Game path (alpha1.conf) opens the window + draws background but hits the
  pre-existing production btdpl.ini vr_sync timeout (sends_wo_rcv) -- not a 3b
  issue. Remaining work tracked in PHASE3-PROGRESS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-03 14:27:58 -05:00
co-authored by Claude Opus 4.8
parent 4b6d910f7b
commit dce89a8571
4 changed files with 386 additions and 20 deletions
+51 -12
View File
@@ -1,9 +1,10 @@
# Phase 3 — Render Backend: Progress
**Status (2026-07-03): Phase 3a complete — the render command stream is fully
captured and decoded, and a captured DIVRGB frame has been reconstructed to
pixels. First image ever produced from the Rel 4.10 VPX protocol without a
real board.**
**Status (2026-07-03): Phase 3a + 3b complete. 3a — the render command stream
is fully captured and decoded, and a captured DIVRGB frame reconstructed to
pixels offline. 3b — a live OpenGL window built into the emulated board draws
each frame in real time inside DOSBox-X. First images ever produced from the
Rel 4.10 VPX protocol without a real board.**
![decoded DIVRGB calibration screen](divrgb-decoded.png)
@@ -71,12 +72,50 @@ PLUGE row — which validates vertices, connectivity, materials, camera and
window mapping in one image. (Division screen x runs opposite to a GL-style
eye space; without negating x the pattern comes out mirrored.)
## Next: 3b — live OpenGL backend
## 3b. Live OpenGL backend (DONE)
Feed the same decode path a live stream inside DOSBox-X instead of a dump:
maintain the node store in `vpxlog.cpp` (or a sibling `vpxrender.cpp`), upload
geometry on set_geom_verts/conns, draw on draw_scene into an OpenGL window
(or the DOSBox surface). The `divrgb.fifodump` fixture allows developing the
backend offline; `flyk yip.scn` (CYCLE, Red Planet geometry) is the next
fixture up once the DOS/4GW sync variant is handled, then the game itself
(`buttee.bgf` etc. via the production content path).
![live GL window rendering DIVRGB](divrgb-live-gl.png)
`VPX_RENDER=1` turns on a live render backend built into `vpxlog.cpp`
(Windows/WGL). The same burst assembler that feeds `VPX_FIFODUMP` now also
feeds an in-process scene store (`scene_burst()``struct VScene`), and each
`vr_draw_scene` publishes a frame snapshot to a dedicated OpenGL window thread
(`rt_main`) that draws it with fixed-function GL. No build-system change was
needed — `opengl32` was already linked, and `vpxlog.cpp` is already in
`hardware/`.
Validated: `flyk divrgb.scn` (`divrgb.conf` with `VPX_RENDER=1`) opens the
"VPX VelociRender (emulated)" window and draws the SMPTE bars live, framed by
the real `camera.spl` spline camera the app sends — matching the offline
`render_capture.py` decode. The window runs on its own thread, so it keeps
displaying the last frame after the DOS app exits.
Design notes:
- Multi-burst payloads (`set_geom_verts`/`conns` continuations) are tracked
with `geom_active` / `conn_active` state, same as the offline decoder.
- Projection: `glFrustum` from the view-node window rect scaled by
`near/window_distance`; a `glScalef(-1,1,1)` handles Division's mirrored
screen-x. Camera is the row-major 3×3 from action 31 loaded as the
modelview rotation, then `glTranslatef(-eye)`.
- Frame handoff is a critical-section-guarded `VFrame` + auto-reset event;
the emulator thread never blocks on GL.
Game path (`alpha1.conf`, full BattleTech v4.10): the window opens and draws
the view background, but the run hits the **pre-existing production-path sync
timeout** (`velocirender_receive timed out — sends_wo_rcv=3`, then
`failed in vr_sync`) — the `btdpl.ini`/netnub launch bursts several sends
before its first receive, which the POLL_THRESHOLD gating stalls. This is not
a 3b issue (the `flyk` clean-launch path renders fine); it is the same
production-sync item still open from Phase 2.
## Remaining
1. **Production-path vr_sync timeout** (`sends_wo_rcv`): the game's
`btdpl.ini`/netnub launch path. Needed before the game itself renders.
2. **Content**: `test.egg` carries no models, so even past sync the game has
no `buttee.bgf`/`mslr.bgf` geometry to draw — needs a real mission/content
tree from the pod image.
3. **DOS/4GW sync variant** for the CYCLE `flyk yip.scn` fixture (Red Planet
geometry) — the older action-check sync.
4. Texturing (`set_texmap_texels`, action 23-data + SVT), lighting, and
depth/material niceties; current backend is flat-shaded untextured polys.