fix(render): #113 - enable GL clip distances for the PView shell pass (phantom exterior staircase)
Attribution (dat-evidenced, supersedes the misplaced-cell hypothesis):
the phantom staircase is the Holtburg MEETING HALL (AAB3 building[0],
model 0x010014C3 at AAB3-local (36,84,116)), NOT an A9B3 building - the
user stood at the A9B3/AAB3 boundary (cell-transit trail in
issue112-gate1.log) and clicked through the hall to the NPC behind it.
The hall's interior stair cells (0x100..0x106, ring climbing z 116->124.5
to the deck hatch) have geometry coincident with the shell's west wall
(both at local x=29.0). Our outdoor per-building flood admits them with
CORRECT tight clip regions (4-6 planes, door-aperture NDC boxes -
Issue113MeetingHallFloodTests proves it), but DrawEnvCellShells drew them
WHOLE: mesh_modern.vert writes gl_ClipDistance from the routed CellClip
slot, and gl_ClipDistance is ignored unless GL_CLIP_DISTANCEi is enabled -
which no caller ever did for the shell pass (born inert in 1405dd8).
Interior staircase painted across the exterior wall; unpickable because
it is cell geometry, not an entity.
Retail oracle: cell geometry IS clipped to the accumulated portal view -
Render::set_view (:343750) installs the view polygon edge planes,
DrawEnvCell submits every cell polygon with planeMask=0xffffffff (:427922)
through ACRender::polyClipFinish. Characters/meshes are NOT poly-clipped
(viewconeCheck path) - entity routing stays cleared, comment scoped.
Fix: enable GL_CLIP_DISTANCE0..7 around exactly the shell pass
(self-contained per feedback_render_self_contained_gl_state; no early-outs
between set and restore). Slot-0 fallback slices (>8-plane regions) still
draw pass-all - the assembler's scissor fallback remains unimplemented and
documented; the new flood test pins 0 such slices at the hall.
Refuted along the way (full evidence in Issue113PhantomStairsDumpTests):
- ONE misplaced interior EnvCell unifying #113+#112+collision gaps: all 17
A9B3 cottage cells share an identical dat Position (nothing to misplace);
the #112 gap is a real 20cm doorway micro-gap 0.23m outside threshold
cell 0x104 (straddles its exterior portal plane at foot radius 0.48);
missing object collision remains #99/A6.P4.
- A9B3 dat content near the spot: no stair geometry in shell (balcony at
z119 + turret roof only), cells (flat 116/118.8), statics, or stabs.
Tests: Core 1389 green (+6 dump facts) / App 224 (+1 flood replay) /
UI 420 / Net 294; pre-existing 4 #99-era failures unchanged.
Visual gate pending: user re-check of the hall west face vs retail.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6d2218cac3
commit
927fd8fde2
3 changed files with 1085 additions and 4 deletions
|
|
@ -341,6 +341,26 @@ public sealed class RetailPViewRenderer
|
|||
// (far→near), per portal_view slice. No drawableCells filter — a cell without a
|
||||
// clip-slot falls through GetCellSlicesOrNoClip to NoClipSlice and draws unclipped
|
||||
// (sealed; per-slice trim returns in Task 4).
|
||||
//
|
||||
// #113 (2026-06-10): the per-slice clip MUST actually clip. Retail clips drawn
|
||||
// CELL geometry to the accumulated portal view — Render::set_view (:343750)
|
||||
// installs the view polygon's edge planes and DrawEnvCell submits every cell
|
||||
// polygon with planeMask=0xffffffff (:427922) through ACRender::polyClipFinish.
|
||||
// Our equivalent (UseShellClipRouting → mesh_modern.vert gl_ClipDistance) was
|
||||
// routed but INERT: gl_ClipDistance writes are ignored unless GL_CLIP_DISTANCEi
|
||||
// is enabled, and no caller enabled it for this pass — so flooded interior cells
|
||||
// drew WHOLE, painting interior geometry across exterior walls (the Holtburg
|
||||
// meeting-hall phantom staircase, AAB3 0x100 stair cell coincident with the
|
||||
// shell's west wall). Self-contained per feedback_render_self_contained_gl_state;
|
||||
// no early-outs between enable and disable. Slot-0 slices (SSBO count=0) still
|
||||
// pass-all — the assembler's >8-plane scissor fallback remains unimplemented
|
||||
// (rare; Issue113MeetingHallFloodTests pins 0 such slices at the hall).
|
||||
// Characters/statics stay unclipped (DrawCellObjectLists): retail's mesh path is
|
||||
// viewcone-check + BoundingType handling, and hard-clipping slices characters at
|
||||
// doorways (the original UseIndoorMembershipOnlyRouting observation).
|
||||
for (int i = 0; i < ClipFrame.MaxPlanes; i++)
|
||||
_gl.Enable(Silk.NET.OpenGL.EnableCap.ClipDistance0 + i);
|
||||
|
||||
foreach (var entry in IndoorDrawPlan.ShellPass(pvFrame))
|
||||
{
|
||||
uint cellId = entry.CellId;
|
||||
|
|
@ -354,6 +374,9 @@ public sealed class RetailPViewRenderer
|
|||
_envCells.Render(WbRenderPass.Transparent, _oneCell);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ClipFrame.MaxPlanes; i++)
|
||||
_gl.Disable(Silk.NET.OpenGL.EnableCap.ClipDistance0 + i);
|
||||
}
|
||||
|
||||
private void DrawCellObjectLists(
|
||||
|
|
@ -396,10 +419,13 @@ public sealed class RetailPViewRenderer
|
|||
|
||||
private void UseIndoorMembershipOnlyRouting()
|
||||
{
|
||||
// Retail's PView portal views decide which cells/objects are eligible,
|
||||
// but DrawMesh only performs portal-view visibility checks before drawing
|
||||
// the mesh. Feeding those 2D views into gl_ClipDistance slices characters
|
||||
// and cell shells at stair/door boundaries, which retail does not do.
|
||||
// For MESHES (characters, statics) retail's DrawMesh performs portal-view
|
||||
// visibility checks (Render::viewconeCheck on the drawing sphere) rather
|
||||
// than hard per-poly clipping — feeding the 2D views into gl_ClipDistance
|
||||
// slices characters at stair/door boundaries, which retail does not do.
|
||||
// CELL SHELL geometry is different: retail clips it to the portal view
|
||||
// (planeMask=0xffffffff per cell polygon, decomp :427922 + :343750) —
|
||||
// DrawEnvCellShells enables exactly that (#113).
|
||||
_envCells.SetClipRouting(null);
|
||||
_entities.ClearClipRouting();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue