Render: FOG restored -- authentic per-map/time/weather fog now renders (task #63)

User: "aren't some levels supposed to have fog?" -- they were, and none showed.
BTDPL.INI (the DPL env INI, L4DPLCFG) authors fog=near far r g b (+ often
nosearchlightfog=) on EVERY map/time/WEATHER leaf; weather is a fixed egg field
(clear/fog/soup). Shipped eggs pin cavern/night/clear -> page dsnitclear
(near 90, far 1100, dark blue). The env pipeline resolved + pushed it to D3D, but
it rendered INVISIBLE: D3DRS_FOGTABLEMODE=D3DFOG_LINEAR (table fog) derives its
factor from the perspective-NONLINEAR z-buffer, so without WFOG the 90..1100 range
collapsed to fog-factor ~1 (no fog everywhere).

Fix (L4VIDEO.cpp world pass): auto-detect D3DPRASTERCAPS_WFOG -> per-pixel W-fog
(smooth, == the arcade dpl_fog_type_pixel_lin); else VERTEX fog (eye-space but
per-vertex -> splotchy on coarse terrain tris, so only a fallback). FOGENABLE + the
fog mode are re-asserted each world-pass frame (the old one-time set got clobbered
per-pass, which is why plain table fog showed nothing). Verified on this GPU:
WFOG present -> per-pixel table fog, user-confirmed smooth.

Also corrected task #20's false "shipped maps define no fog" comment (it checked
.MAP/.RES, not BTDPL.INI). Env hooks: BT_FOGMODE=table|vertex|off, BT_WEATHER=
clear|fog|soup, BT_FOG="near far r g b" (now honored on the authored branch too);
[fog] resolved/model diagnostics. KB: rendering.md fog section added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-13 21:24:06 -05:00
co-authored by Claude Opus 4.8
parent a9c0d2c854
commit 083b148bb0
2 changed files with 78 additions and 8 deletions
+15
View File
@@ -52,6 +52,21 @@ DECLOUDS must stay in the sky pass). Authored TEXTURE **SCROLL** (BMF TEXTURE ta
`L4DPLCFG`): resolves map+time → clip/fog/ambient + a directional sun. Bring-up stubs
(EnsureValidProjection / per-frame ambient / uninit cloud colours) had clobbered it — now they
RE-ASSERT the env values. Debug: copy BTDPL.INI → *DBG.INI with `debug=True`. [T2]
- **Fog — per map/time/WEATHER (task #63).** `BTDPL.INI` authors `fog=<near> <far> <r> <g> <b>` (+ often
`nosearchlightfog=`) on EVERY map/time/weather leaf. WEATHER is a fixed authored egg field
(`clear`/`fog`/`soup`, `mission->GetMissionWeather()`; missing = fatal in the arcade); the env pipeline
branches location→time→weather to the leaf. Shipped eggs pin `cavern/night/clear` → page `dsnitclear`
(near 90, far 1100, dark blue 0.1,0.1,0.12); `fog``dsnitfog` (500), `soup``dsnitsoup` (300). The
arcade fog model is per-PIXEL linear (`dpl_fog_type_pixel_lin`, dpl.h:265). **It rendered INVISIBLE in
the port:** `D3DRS_FOGTABLEMODE=D3DFOG_LINEAR` (table fog) reads the perspective-NONLINEAR z-buffer, so
without WFOG the authored 90..1100 range collapsed to fog-factor≈1 (no fog). FIX (L4VIDEO.cpp world
pass ~8194): auto-detect `D3DPRASTERCAPS_WFOG` → per-pixel W-fog (smooth, == the arcade); else VERTEX
fog (eye-space but per-vertex → splotchy on coarse terrain tris); FOGENABLE + mode re-asserted each
world-pass frame (the old one-time set got clobbered per-pass). **Task #20's "shipped maps define no
fog" was WRONG** — it checked `.MAP`/`.RES`, but fog lives in BTDPL.INI (the DPL env INI), as in the
arcade. Night fog is dark BY DESIGN (distance→murk, not light haze); day pages author light haze. Env:
`BT_FOGMODE=table|vertex|off`, `BT_WEATHER=clear|fog|soup`, `BT_FOG="near far r g b"` (all branches);
`[fog] resolved`/`[fog] model` log lines. [T1 pipeline / T0 arcade model / T2 fix]
- **Projection / stencil (task #55):** the BTDPL.INI `viewangle=60` is the **HORIZONTAL** FOV —
authentic 60×47 frustum at 4:3; fovY derived via `BTFovYFromHorizontal` (L4VIDEO.cpp), applied at
all 5 projection sites (it was mis-applied as vertical). The device depth-stencil is now