forked from Ports/goldeneye-pc-port
D953: a wider Field of view no longer pulls model LOD, prop fog fade and fog visibility closer
c_lodscalez is built from the rendered FOV (D222), so Video.FovScale moved every model LOD switch, the prop fog fade and the fog-range visibility test closer (x0.58 at 150); half-fogged props such as the Surface windows went fully invisible and flickered while turning. All three now use the game's own FOV (portLodScaleOwnFov); identity at the default FOV.
This commit is contained in:
1 parent
a77bd4e03d
commit
e70fffffcd
6 files changed
+77
-1
No files matched your search
@@ -200,6 +200,7 @@ A single campaign pass with these on the checklist would clear most of them.
|
||||
| Steam Deck preset skipped when first launched from Desktop Mode | verify | D283 | Fixed on `release/v0.4.1`: the Deck is detected by DMI hardware id (Valve Jupiter/Galileo; `STEAMOS` as a second signal) and the preset applies once per ini, only while Fullscreen/Maximized are untouched. Only a Windows build and a Linux `-fsyntax-only` check ran. **Owed: one run on a real Deck** (Desktop-Mode-created ini, then Game Mode; expect fullscreen 1280x800 and the log line `video: Steam Deck (DMI Valve ...)`). The Known-issues row goes when this ships. |
|
||||
| Windows 7 | open | #98 | **Re-checked 2026-10-02: likely feasible around 1.0.** The exe imports no Windows 8+ functions and the bundled SDL2 2.32.10 still supports Windows 7. The real blocker is the first-run converter `ge007-convert.exe` (PyInstaller, Python 3.9+): the native C converter (#6 Part B) removes it, or a separate Python 3.8 build. Work: one Windows 7 VM test, then manual per-release checks (CI cannot test it). Supersedes the earlier 'won't-fix' call. |
|
||||
| Alt-tab haze + fast alt-tab recovery | open (v0.7.0, maintainer 2026-10-10) | D578 | Maintainer 2026-10-10 (v0.6.0 build, Windows 120 Hz): alt-tabbing leaves a hazy picture; fast repeated alt-tab is wonky and recovers only after a while or more alt-tabbing. Not new in v0.6.0 (was an owed check). Known issue in the v0.6.0 notes. QoL fix: clean focus-loss/regain path (context/FBO state, present queue reset). |
|
||||
| Deck: max Field of view feels choppier while turning | open (maintainer 2026-10-13; goal: fully resolved, not tied to v0.6.0) | D953 | At FOV 90 (menu max) turning feels worse than at 60, at 60 and 90 fps. Frame pacing measured identical at both FOVs. Lead: FovScale pulls every model LOD switch 1.73x closer, and depth-based LOD flips off-axis objects while turning (Dam turn probe: 0 flips at 60 deg, 400 at 90 deg, 120 with the fix candidate on `fix/d953-fov-lod`). Pass 2 (10-13 evening): prop fog fade and fog-range visibility fixed the same way; on Surface LOD/fade/visibility do not change while turning, so they are not the feel. Maintainer: objects "update not at the right speed" (object motion is not interpolated at 90, plan D955). **Next:** D955 Stage 0, and one Deck `GE_D193=1` run per FOV for 2-tick game steps. |
|
||||
| Doors and guards flicker at 90 fps (not at 60) | fixed 2026-10-13 (D954); maintainer Deck check owed | D954 | In-between presents drew props (chrs, doors, effects) at the exact camera while rooms used the blended one, so props jumped against the world whenever the camera moved (Surface turn on Windows: 0.4-0.5 deg mean, up to 1.8 deg). Present in v0.6.0 at 90 fps. Fix in `gfx_pc.cpp`: props' plain perspective gets the room camera blend (`P * R^-1 * Rb`) up to the first-person gun. **Owed:** Deck at 90 fps, Surface doors/guards, and the gun must not move while turning. |
|
||||
| Objects move at 60 Hz steps at 90 fps (props, doors, guards) | implemented 2026-10-13 (D955); maintainer Deck check owed | D955 | In-between presents drew objects at their tick pose (only the camera was blended). Now blended per joint, keyed by (Model*, joint) from a game-thread snapshot, rebased onto the new camera; exact on room-origin changes, failed gates, split-screen. Dam on Windows: 99.6% of object joint loads blended. **Owed:** Deck at 90: guards walking, gun in hand, hats, deaths, shadows, doors, Facility stall doors/sinks (the old ghost site), room boundaries. Vehicles later. |
|
||||
| Windows display scaling: the game is not DPI-aware on scaled displays | fixed 2026-10-10 (D626); maintainer by-eye on a scaled display owed | D626 | Seen 2026-10-07 during the v0.5.0 4K captures: on a 3840x2160 display at 125% Windows gives the game a 3072x1728 surface and stretches it, so the picture is softer than native. `gfx_sdl2.cpp` sets `SDL_HINT_WINDOWS_DPI_AWARENESS` only when `allow_hidpi` is off; setting it (`permonitorv2`) on the HiDPI path too renders at native resolution. Workaround today: environment variable `SDL_WINDOWS_DPI_AWARENESS=permonitorv2`. |
|
||||
|
||||
@@ -464,6 +464,7 @@ D645,FIXED,"Original 1.1: F10 ""Invert look"" did not invert vertical look (#145
|
||||
D646,FIXED,"F10 dropdown popup drew over the hint/tooltip panel (popup bounded by the screen edge, not the settings box) —",FIXED 2026-10-12 (ddGeom bounded to the box; maintainer-verified)
|
||||
D951,OPEN,"v0.6.0 release gate: Windows golden sweep flags are timing noise in the test, not rendering changes —",OPEN (test-side; 2026-10-13)
|
||||
D952,FIXED,"macOS: black window, no frame, when the game starts while the display is asleep (SDL3 Cocoa VSync waits forever on a CVDisplayLink that never started) —","FIXED 2026-10-13 (port-only, gfx_sdl2.cpp; Mac A/B:"
|
||||
D953,OPEN,Deck: wide Field of view feels choppier while turning —,OPEN (fix candidate on fix/d953-fov-lod; Dam turn probe 90 deg:
|
||||
D954,FIXED,"Doors and guards flicker at 90 fps, not at 60:","FIXED 2026-10-13 (port-only, gfx_pc.cpp + interpportal.c; Windows-measured; Deck check owed)"
|
||||
D955,OPEN,"Objects (props, doors, guards) moved at the 60 Hz tick inside a 90 Hz picture:","IMPLEMENTED 2026-10-13 (port-only, gfx_pc.cpp + interpportal.c; Windows-measured; Deck feel check owed)"
|
||||
D607,OPEN,Address model unified into one header:,DONE 2026-10-07 (macos branch; Windows identity gate:
|
||||
|
||||
|
@@ -875,6 +875,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D646 | **F10 dropdown popup drew over the hint/tooltip panel (popup bounded by the screen edge, not the settings box)** — full `## D646` entry at file tail | FIXED 2026-10-12 (`ddGeom` bounded to the box; maintainer-verified) |
|
||||
| D951 | **v0.6.0 release gate: Windows golden sweep flags are timing noise in the test, not rendering changes** — full `## D951` entry at file tail | OPEN (test-side; 2026-10-13) |
|
||||
| D952 | **macOS: black window, no frame, when the game starts while the display is asleep (SDL3 Cocoa VSync waits forever on a CVDisplayLink that never started)** — full `## D952` entry at file tail | FIXED 2026-10-13 (port-only, `gfx_sdl2.cpp`; Mac A/B: unfixed 3/3 hang, fixed 0/5) |
|
||||
| D953 | **Deck: wide Field of view feels choppier while turning — FovScale moves every model LOD switch 1.73x closer (c_lodscalez built from the rendered fovy, D222)** — full `## D953` entry at file tail | OPEN (fix candidate on `fix/d953-fov-lod`; Dam turn probe 90 deg: 400 -> 120 LOD flips, 60 deg: 0; maintainer LodDistance feel test owed) |
|
||||
| D954 | **Doors and guards flicker at 90 fps, not at 60: in-between presents drew props at the exact camera while rooms used the blended one** — full `## D954` entry at file tail | FIXED 2026-10-13 (port-only, `gfx_pc.cpp` + `interpportal.c`; Windows-measured; Deck check owed) |
|
||||
| D955 | **Objects (props, doors, guards) moved at the 60 Hz tick inside a 90 Hz picture: in-between presents now blend object motion per joint** — full `## D955` entry at file tail | IMPLEMENTED 2026-10-13 (port-only, `gfx_pc.cpp` + `interpportal.c`; Windows-measured; Deck feel check owed) |
|
||||
|
||||
@@ -22017,6 +22018,25 @@ FpsCap = 60'`: 20/21 PASS; statue REGRESSION (4.66%, frame 900).
|
||||
|
||||
**Status.** FIXED.
|
||||
|
||||
## D953: wide Field of view feels choppier on the Deck while turning — LOD switches move closer with FovScale — OPEN (fix candidate, maintainer feel test owed)
|
||||
|
||||
**Symptom (maintainer, Deck).** At the maximum Field of view (90 deg vertical in the menu = `Video.FovScale = 150`) turning feels choppier than at the default 60 deg, at 60 AND 90 fps; frame times look fine. Maintainer can't name a specific artefact ("it just feels worse", "mostly turning").
|
||||
|
||||
**Ruled out (Deck Game Mode, deckrunner, Dam `--script turn`, 45 s, maintainer's v0.6.0 ini, 2 runs each).** Frame delivery is identical at 60 vs 90 deg: 60 fps 0 SLOW frames both; 90 fps ~99% of present gaps in 9.5-12 ms both, softened/exact interpolation decisions the same (pre-softened 285/244 vs 272/235, late exact 4/4 vs 2/1), no extra ROOMCHANGE/REACH/CUT/FALLBACK at 90 deg. Turn speed (uses the game's own fovy), culling (D222), the fog edge (D503).
|
||||
|
||||
**Cause (code).** `c_lodscalez` (`currentPlayerSetCameraScale`, `src/game/bondview.c`) is tan(fovy/2)/tan(30 deg) and is built from the RENDERED fovy (D222 `frCullFovY`), so FovScale 150 multiplies every model's LOD distance (`modelUpdateDistanceRelations`, `src/game/model.c`, distance = view-space depth * c_lodscalez) by tan(45)/tan(30) = 1.73: switches move 1.73x closer. The distance is view-space DEPTH, not radial distance, so it changes fastest for objects off to the side while turning — exactly the objects a wide FOV puts on screen.
|
||||
|
||||
**Measured (temp probe, LOD-node visibility flips per 600 frames, frames 1200-2400 = the turning part; identical in both runs of each case).** 60 deg: 0 (fix on or off). 90 deg v0.6.0: 400. 90 deg with the fix: 120. One visible model swap is usually 2 node flips. The residual 120 are objects whose depth crosses the authored (60-deg-equivalent) thresholds while turning; at 60 deg they are presumably off screen (not measured; the probe can't tell on/off screen).
|
||||
|
||||
**Fix candidate (`fix/d953-fov-lod`, `src/game/model.c`, `#ifdef PORT`, D565 pattern).** Multiply the LOD distance by tan(own/2)/tan(rendered/2), own = `viGetFovY()`, rendered = `c_perspfovy` (what c_lodscalez was built from, so portScaleFovY's clamps and title-screen exemption carry over). Identity whenever the two are equal (all defaults). Video.LodDistance still composes on top. Builds (Windows untested; Linux WSL Ubuntu-24.04 build deployed to the Deck as `~/ge007-v050/ge007.x86_64.d953`).
|
||||
|
||||
**Owed.** (1) Maintainer feel test that discriminates the hypothesis with NO build: v0.6.0 at FOV 90, `LodDistance` 200 -> ~350 (cancels the 1.73x; roughly what the fix does), then higher (the residual edge swaps). If that removes the feeling, LOD is the cause; choose between this fix, an automatic LodDistance boost at wide FOV, or both (the residual 120 suggests the fix alone may not be 100%). If it does not, LOD is not the cause. (2) Then Windows build + per-patch golden diff (identity at defaults).
|
||||
|
||||
**Pass 2 (2026-10-13 evening): all render consumers of c_lodscalez, and a measurement on Surface.** Besides model LOD, two render paths scale with the rendered FOV: the prop/guard fog fade (`propobj.c` `chrobjFogVisRangeRelated`) and the prop fog-range visibility test (`sub_GAME_7F054C58`). Their D222/D218 compensation divides by `portDrawDistanceMultiplier()`, which was FOV-linked only through `Video.DrawDistanceAutoFov`; that became a legacy option (off), so the multiplier is the flat Video.DrawDistance and at FovScale 150 props faded and popped at x0.58 the default-FOV distance. All three now use one helper, `portLodScaleOwnFov()` (`port/src/video.c`, tan(own/2)/tan(rendered/2), cached; 1.0 at defaults). AI paths were already corrected (D565); frustum culling keeps the rendered FOV (D222). Turning is not FOV-scaled (bondview2.c uses the game's fovy; `input.c` only declares portScaleFovY).
|
||||
Measured (Windows, Surface 1, 1280x800, 60 fps, same scripted look left/right, temp probe from frame 400, since removed): LOD flips 37 / 37 / 37, fade-state changes 1 / 1 / 1, visibility flips 0 / 2 / 0 (FOV 100 / 150 / 150 + fix). Evaluations in the partial fog fade: 256 / 0 / 246, so at max FOV without the fix the props that sit half-faded in Surface's fog at the default FOV were fully invisible; the fix restores them. **On Surface none of these change while turning, so they do not explain the maintainer's "default FOV feels smoother at any fps" (Deck, Surface, 90 fps, D954 build).** Remaining FOV-dependent factor, by code: image-level. At bilinear (the Deck ini: TextureFilter 1) only textures the game flags as mipmapped get mips (`gfx_opengl.cpp` upload), the rest are minified with plain GL_LINEAR, and a 90-deg vertical FOV minifies every surface ~1.7x more, so more of the frame shimmers while the camera moves; thin geometry goes sub-pixel likewise (MSAA 2x). Plus the rectilinear stretch at 116 deg horizontal (edge vs centre screen speed 3.6x, against 1.9x at the default). Discriminating test, no build: FOV 90 with Texture filter = Trilinear (mips on every texture).
|
||||
Maintainer (same evening) rejects the texture lead: "models/objects kinda lag behind... like tearing except nothing is tearing... just seem to update not at the right speed." That matches the 90 fps path: in-between passes blend only the camera (D578, D954), so object motion (props and matrix-skinned chrs) still steps at the 60 Hz tick inside a 90 Hz picture. Plan D955 (object-motion interpolation keyed by (Model*, joint), no game hooks) is reviewed (go with changes) and staged; Stage 0 is instrumentation only. Still unexplained: why max FOV feels worse than the default at the same fps. Open lead: GE's wall-clock tick step (frametiming.c) taking 2-tick steps more often at wide FOV on the Deck; never measured (Deck summaries record presents and draw time only); `GE_D193=1` logs render frames vs sim ticks per second.
|
||||
|
||||
**Status.** OPEN.
|
||||
## D954: doors and guards flicker at 90 fps (not at 60) — in-between presents drew props at the exact camera, rooms at the blended one — FIXED 2026-10-13 (port layer; maintainer Deck check owed)
|
||||
|
||||
**Symptom (maintainer, Deck, Surface).** Doors and guards flicker at 90 fps; never at 60 fps. First seen on a D953 test build, but nothing in D953 depends on frame rate (LOD is chosen once per game tick and the in-between passes replay the same list), so the trigger is the D578 interpolation, which only runs above 60 fps.
|
||||
|
||||
@@ -312,6 +312,37 @@ f32 portScaleFovY(f32 fovy, s32 isTitleScreen)
|
||||
return fovy;
|
||||
}
|
||||
|
||||
/* D953: tan(own/2) / tan(rendered/2), own = the game's fovy (viGetFovY, zoom
|
||||
* included), rendered = c_perspfovy (what currentPlayerSetCameraScale built
|
||||
* c_lodscalez from: portScaleFovY's widening, clamps and title exemption).
|
||||
* c_lodscalez is tan(fovy/2)-proportional, so multiplying it by this gives
|
||||
* the value the game would compute at its own FOV. Every RENDER consumer of
|
||||
* c_lodscalez (model LOD, prop fog fade, prop fog-range visibility) uses it,
|
||||
* so Video.FovScale widens the view without pulling detail swaps, fades and
|
||||
* pop-in closer (x0.58 at 150) -- they are view-depth tests, so the pulled-in
|
||||
* band swept over off-axis objects while turning. Frustum culling (D222)
|
||||
* keeps the rendered value. 1.0f whenever the two are equal (all defaults).
|
||||
* Cached on the pair (called per model node and per prop). */
|
||||
f32 portLodScaleOwnFov(void)
|
||||
{
|
||||
extern f32 viGetFovY(void);
|
||||
extern f32 getPlayer_c_perspfovy(void);
|
||||
static f32 lastOwn = -1.0f, lastEff = -1.0f, lastK = 1.0f;
|
||||
const f32 own = viGetFovY();
|
||||
const f32 eff = getPlayer_c_perspfovy();
|
||||
if (own == lastOwn && eff == lastEff) {
|
||||
return lastK;
|
||||
}
|
||||
lastOwn = own;
|
||||
lastEff = eff;
|
||||
lastK = 1.0f;
|
||||
if (own > 0.0f && eff > 0.0f && own != eff) {
|
||||
const f32 h = 3.14159265f / 360.0f;
|
||||
lastK = tanf(own * h) / tanf(eff * h);
|
||||
}
|
||||
return lastK;
|
||||
}
|
||||
|
||||
/* D468: the factor portScaleFovY applies to an in-level fovy (clamps
|
||||
* ignored), so gameplay can recover the game's own FOV from the rendered one.
|
||||
* 1.0f at the defaults (native widescreen on, FovScale 100). */
|
||||
|
||||
@@ -1943,6 +1943,17 @@ void modelUpdateDistanceRelations(Model* model, ModelNode* node)
|
||||
else
|
||||
{
|
||||
distance = -mtx->m[3][2] * getPlayer_c_lodscalez();
|
||||
#ifdef PORT
|
||||
/* D953: c_lodscalez is built from the RENDERED fovy (D222), so a
|
||||
* wider Video.FovScale moved every model's LOD switch closer (x1.7
|
||||
* at 150) and models swapped detail more often while turning.
|
||||
* Rescale to the game's own fovy (port/src/video.c
|
||||
* portLodScaleOwnFov; zoom kept, identity at the defaults). */
|
||||
{
|
||||
extern f32 portLodScaleOwnFov(void);
|
||||
distance *= portLodScaleOwnFov();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (g_ModelDistanceScale != 1)
|
||||
{
|
||||
|
||||
+13
-1
@@ -13576,6 +13576,16 @@ f32 chrobjFogVisRangeRelated(PropRecord *prop, f32 size)
|
||||
extern f32 portDrawDistanceMultiplier(void);
|
||||
temp_f12 /= portDrawDistanceMultiplier();
|
||||
}
|
||||
/* D953: the FOV half of the above stopped holding when
|
||||
* Video.DrawDistanceAutoFov became a legacy option (off): the
|
||||
* multiplier is now the flat Video.DrawDistance, so at FovScale 150
|
||||
* guards and props faded at x0.58 the distance of the default FOV,
|
||||
* a view-depth test that swept over off-axis props while turning.
|
||||
* Rescale c_lodscalez to the game's own fovy (identity at defaults). */
|
||||
{
|
||||
extern f32 portLodScaleOwnFov(void);
|
||||
temp_f12 *= portLodScaleOwnFov();
|
||||
}
|
||||
#endif
|
||||
temp_f12 = ((((prop->zDepth - nfd->MaxObfuscationRange) * 100.0f) / size) + nfd->MaxObfuscationRange) * temp_f12;
|
||||
|
||||
@@ -13619,10 +13629,12 @@ bool sub_GAME_7F054C58(coord3d *coord, f32 arg1)
|
||||
f32 scalez = getPlayer_c_lodscalez();
|
||||
#ifdef PORT
|
||||
/* D222/D218 follow-up -- see chrobjFogVisRangeRelated above,
|
||||
* same fix for this sibling visibility test. */
|
||||
* same fix for this sibling visibility test (D953 too). */
|
||||
{
|
||||
extern f32 portDrawDistanceMultiplier(void);
|
||||
extern f32 portLodScaleOwnFov(void);
|
||||
scalez /= portDrawDistanceMultiplier();
|
||||
scalez *= portLodScaleOwnFov();
|
||||
}
|
||||
#endif
|
||||
sp20 = ((sp20 - ptr->z) * 100 / arg1 + ptr->z) * scalez;
|
||||
|
||||
Reference in new issue
Block a user