fix #130: doorway-slice scissor cut the aperture's top/right pixel row

The user's "thin strip of background color along the TOP outer edge of a
doorway, looking out from inside" is the landscape-slice scissor box, not
the W=0 clip port.

Mechanism (pinned headlessly, Issue130DoorwayStripTests, 147 eye/gaze
combos at the real Holtburg A9B4 0x0170 exit door):
- BeginDoorwayScissor converted the slice NDC AABB to pixels as
  Floor(origin) + Ceiling(size). The far edge floor(min)+ceil(max-min)
  lands up to ONE PIXEL SHORT of the true top/right edge at unlucky
  fractional alignments (captured: top edge y=0.7938 @1080p -> row 968
  cut; right edge column 1296 @1920 cut).
- The scissor brackets the ENTIRE landscape slice (sky, terrain, outdoor
  statics, weather). The exit-portal SEAL stamps the full raw aperture at
  true depth and the shell wall ends at the aperture edge, so the cut row
  never receives any color write -> clear color, flickering with eye
  movement as the fractional alignment shifts.
- This violated AD-17's own invariant (over-inclusion is safe,
  UNDER-inclusion is the bug class). No register change: the fix restores
  the row's documented doctrine.

Lead 1 (987313a W=0 clip port regression) REFUTED by the same harness:
the CPU polygon pipeline (ProjectToClip -> ClipToRegion merges ->
ClipPlaneSet planes) is sub-pixel exact against the raw aperture
projection (worst 0.54 px, 0.00 px aligned). For an all-in-front doorway
polygon the port is bit-identical to the old 1e-4 path by construction.
The EyeInsidePortalOpening rescue stays deleted.

Fix: conservative outer bound floor(min)/ceil(max) extracted to
NdcScissorRect.ToPixels (GL-free; containment property proven in the
header comment); BeginDoorwayScissor delegates.

Pins:
- NdcScissorRectTests: center-inside containment across 251 fractional
  alignments x 2 framebuffer sizes + both captured regression cases.
- Issue130DoorwayStripTests: production flood + assembler at the real
  exit door; asserts the scissor never cuts a plane-admitted fragment
  (worstScissorGap 0.00 px post-fix, was 10.8 px capped) and the CPU
  pipeline stays sub-pixel exact (canary 1.2 px).

Suites: App 252+1skip / Core 1439+2skip / UI 420 / Net 294 green.
Awaiting the user visual gate at a cottage doorway.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-12 13:31:43 +02:00
parent 0cb97aa594
commit 6c4b6d64d9
5 changed files with 494 additions and 40 deletions

View file

@ -4512,38 +4512,45 @@ math).
## #130 — Background-color strip along the TOP outer edge of a doorway when looking out from inside
**Status:** OPEN
**Status:** FIX SHIPPED — awaiting user visual gate
**Severity:** LOW-MEDIUM (small strip, but on the most-stared-at pixels in the game)
**Filed:** 2026-06-12 (user report, post-#119-close session; "also NOW" —
possibly new since the W=0 clip port `987313a`)
**Component:** render — doorway aperture edge (seal/punch/OutsideView seam)
**Filed:** 2026-06-12 (user report, post-#119-close session)
**Component:** render — doorway-slice scissor box math (AD-17 family)
**Symptom (user):** standing inside looking out through a doorway, a
thin strip of background (clear/world) color runs along the OUTER edge
of the TOP of the doorway opening.
**Leads (capture first — plausibly a `987313a` regression):**
1. The W=0 port changed `ProjectToClip` (exact w>=0, no 1e-4 epsilon)
and DELETED the `EyeInsidePortalOpening` rescue — the OutsideView
region through a near doorway is computed slightly differently now.
If the OutsideView's top edge sits ~1 px BELOW the aperture's drawn
shell edge, terrain/outdoor geometry isn't drawn in that strip while
the interior seal/punch still cleared it → background color.
Suspects within the port: `MergeSubPixelVertices` shaving a top
vertex; the exact-w boundary vs the old epsilon shifting the
projected edge; the deleted rescue no longer substituting the full
view for an eye-pressed doorway.
2. The interior SEAL depth vs the shell top edge (the #118-era
machinery) — a 1-px mismatch between the seal polygon and the shell
aperture would show the clear color exactly at an edge.
**Root cause (pinned headlessly 2026-06-12, `Issue130DoorwayStripTests`
— 147 eye/gaze combos at the real A9B4 0x0170 exit door):** the
`BeginDoorwayScissor` NDC→pixel conversion (`Floor(origin) +
Ceiling(size)`) put the box's far edge at `floor(min)+ceil(maxmin)` —
up to ONE PIXEL SHORT of the true top/right edge at unlucky fractional
alignments. The scissor brackets the ENTIRE landscape slice (sky,
terrain, statics, weather), the seal stamps the full aperture at true
depth, and the shell ends at the aperture edge — so the cut pixel row
never receives color: a background strip along the top edge that comes
and goes as the eye moves (alignment shifts). Captured live by the
harness: top edge y=0.7938 at 1080p → row 968 cut; right edge column
1296 cut at 1920. This violated AD-17's own doctrine (over-inclusion
safe, under-inclusion is the bug class).
**Next:** screenshot + [viewer]/[pv-dump] capture at a doorway showing
the strip; diff the OutsideView top edge NDC vs the aperture polygon's
projected top edge for that frame (the CornerFloodReplay harness
machinery can replay the frame headlessly once the eye/cell are
captured). If it reproduces at the same doorway with `987313a` reverted
locally, it's the port's edge math; fix the math, never re-add the
rescue.
**Lead 1 REFUTED:** the W=0 clip port `987313a` is exonerated by the
same harness — the CPU polygon pipeline (ProjectToClip → ClipToRegion
merges → ClipPlaneSet planes) is sub-pixel exact against the raw
aperture projection (worst 0.54 px; 0.00 px in the aligned case). For
an all-in-front doorway polygon the port is bit-identical to the old
path by construction (the W clip pass only runs when a vertex has
w < 0).
**Fix:** conservative outer bound `floor(min)/ceil(max)` extracted to
`NdcScissorRect.ToPixels` (GL-free, unit-tested); `BeginDoorwayScissor`
delegates. Pins: `NdcScissorRectTests` (containment property + both
captured alignments) + `Issue130DoorwayStripTests` (scissor never cuts
plane-admitted fragments; CPU-pipeline exactness canary ≤1.2 px).
**Gate:** stand inside any cottage, look out the door, sweep the gaze —
no background strip at the top edge at any alignment.
---