fix #131+#132: landscape translucents drawn AFTER the #124 look-ins (FlushAlphaList deferral)
The user's screenshot pair re-attributed both reports to ONE mechanism -
a compositing gap in the #124 look-in sub-pass:
- #131: the portal swirl (a TRANSLUCENT MESH, not only particles) stood
exactly in front of the hall's doorway. The slice drew it BEFORE the
look-in sub-pass; translucents write no depth, so the hall's interior
- drawn into its far-Z-punched aperture - overpainted the swirl.
Outdoors the look-ins are the post-stage merge path, so the swirl
survives ("stepping out it pops into existence").
- #132: the candle/lantern flame is an attached emitter in the slice's
Scene-particle pass - same pre-look-in placement, same erasure
whenever "the opening through a house" sat behind it; against a wall
nothing overdraws it. Background-dependence explained exactly.
Retail cannot exhibit this class: every alpha draw of the landscape
stage is collected and flushed ONCE after LScape::draw
(D3DPolyRender::FlushAlphaList, PView::DrawCells pc:432722) - i.e.
after all building look-ins.
Port (the two-phase split): DrawLandscapeThroughOutsideView now runs
EARLY per slice (sky, terrain, outdoor STATIC meshes - the look-in
punches need their depth to mark against, the #117 lesson), then the
#124 look-ins, then LATE per slice (outside-stage dynamics' meshes +
ALL attached scene particles + weather + SkyPostScene), then the #131
unattached pass. New RetailPViewLandscapeLateSliceContext carries the
dynamics survivors + the particle-owner set (statics + dynamics cone
survivors). GameWindow's slice handler split accordingly. Outdoor
roots: no look-ins live in the stage, so the net order is unchanged
(zero behavior change outdoors).
Register: AP-34 added - the two-phase split vs retail's single
deferred flush, with the residuals recorded (outdoor-root slice
particles still draw before merged building interiors - the unreported
outdoor sibling; building exteriors' own translucent batches draw
early).
The earlier #131 unattached-emitter pass (1d3f9a8) remains - it fixes
an independent hole (that class had NO indoor pass at all) - and now
runs at the end of the late phase.
Suites: App 259+1skip / Core 1439+2skip / UI 420 / Net 294 green.
Awaiting the user gate: swirl through the doorway, candle flame with
the opening behind it, far-building interiors (#124).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1d3f9a8c97
commit
20d17304d7
4 changed files with 177 additions and 40 deletions
|
|
@ -4619,35 +4619,59 @@ cell classification is a future port.
|
|||
`[outstage]` (per-slice routing + cone verdicts) + `[outstage-pt]`
|
||||
(slice id set, attached matched count, unattached count).
|
||||
|
||||
**FIX 1 INSUFFICIENT (user screenshots, same evening):** the swirl is
|
||||
the portal's TRANSLUCENT MESH, not (only) unattached particles. The
|
||||
real mechanism — shared with #132 — is the #124 look-in ordering: the
|
||||
slice drew the portal mesh (and all scene particles) BEFORE the look-in
|
||||
sub-pass; translucents write no depth, so the far building's interior
|
||||
(drawn into its far-Z-punched aperture) overpainted them wherever a
|
||||
look-in opening sat behind them on screen. Both screenshots show the
|
||||
swirl exactly in front of the hall's doorway. Retail cannot have this
|
||||
bug: all landscape-stage alpha draws are deferred into ONE flush after
|
||||
LScape::draw (`D3DPolyRender::FlushAlphaList`, DrawCells pc:432722).
|
||||
|
||||
**FIX 2 (the FlushAlphaList deferral, same commit family as #124):**
|
||||
the landscape stage is now TWO phases per frame — EARLY per slice: sky,
|
||||
terrain, outdoor static meshes (the look-in punches need their depth, the
|
||||
#117 lesson); then the #124 look-ins; then LATE per slice: outside-stage
|
||||
dynamics' meshes + ALL attached scene particles + weather + the
|
||||
unattached pass. Outdoor roots keep their existing order (no look-ins in
|
||||
the stage; net order unchanged). Residual (documented, AP-34): under
|
||||
OUTDOOR roots slice particles still draw before merged building
|
||||
interiors (the outdoor sibling of this bug, unreported); building
|
||||
exteriors' own translucent batches draw early.
|
||||
|
||||
**Gate:** stand inside, look out the doorway at the town portal — the
|
||||
swirl renders through the door.
|
||||
swirl renders through the door; the candle flame (#132) stays visible
|
||||
with the through-opening behind it.
|
||||
|
||||
---
|
||||
|
||||
## #132 — Candle flame disappears when the through-opening background is behind it
|
||||
|
||||
**Status:** OPEN
|
||||
**Status:** FIX SHIPPED (shared mechanism with #131 fix 2) — awaiting user visual gate
|
||||
**Severity:** LOW-MEDIUM
|
||||
**Filed:** 2026-06-12 (user report, #124 gate session)
|
||||
**Component:** render — cell-particle compositing vs aperture pixels
|
||||
**Component:** render — slice particles drawn before the #124 look-ins
|
||||
|
||||
**Symptom (user, axiom):** "I have a candle, when I look at the candle
|
||||
when a wall is behind it it shows, but if I turn a bit and the opening
|
||||
through a house is behind it candle light disappears."
|
||||
|
||||
**Reading:** BACKGROUND-dependent disappearance — the candle (and its
|
||||
owner static) stays in view; only what is behind it changes. That rules
|
||||
out viewcone/owner culling (which keys on the candle's own position)
|
||||
and points at per-pixel state in the aperture region: depth left by the
|
||||
punch/seal/look-in machinery at those pixels, draw order of the cell
|
||||
particle pass vs the aperture passes, or blend state. Candidate overlap
|
||||
with the #124 look-in sub-pass (new pre-clear content in exactly those
|
||||
pixels) — check whether the symptom predates `77cef4c` by looking at a
|
||||
candle in front of a doorway WITHOUT a through-house view.
|
||||
**Root cause (= #131's fix-2 mechanism):** the candle/lantern's flame
|
||||
is an attached emitter drawn in the landscape slice's Scene-particle
|
||||
pass, which ran BEFORE the #124 look-in sub-pass. Particles write no
|
||||
depth; whenever a look-in opening ("the opening through a house") sat
|
||||
behind the flame on screen, the far building's interior — drawn into
|
||||
its far-Z-punched aperture — overpainted the flame. Against a plain
|
||||
wall (no look-in aperture behind), nothing overdraws it → visible.
|
||||
Background-dependence explained exactly.
|
||||
|
||||
**Next:** repro at the spot + `ACDREAM_PROBE_OUTSTAGE` lines for the
|
||||
same frame; then a depth-state walkthrough of the aperture pixels for
|
||||
the cell-particle pass.
|
||||
**Fix:** the landscape stage's two-phase split (see #131 FIX 2): all
|
||||
scene particles moved to the LATE phase, after the look-ins.
|
||||
|
||||
**Gate:** the candle at the original spot — flame stays visible when
|
||||
the through-opening is behind it.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ accepted-divergence entries (#96, #49, #50).
|
|||
|
||||
---
|
||||
|
||||
## 3. Documented approximation (AP) — 33 rows
|
||||
## 3. Documented approximation (AP) — 34 rows
|
||||
|
||||
| # | Divergence | Where (file:line) | Why it is safe / justified | Risk if assumption breaks | Retail oracle |
|
||||
|---|---|---|---|---|---|
|
||||
|
|
@ -129,6 +129,7 @@ accepted-divergence entries (#96, #49, #50).
|
|||
| AP-31 | Scenery placement drift + the 0xA9B1 road-edge tree — WB-upstream divergences from retail, ACCEPTED (**#49/#50**, 2026-05-11) | `src/AcDream.Core/World/SceneryGenerator.cs` (via `WbSceneryAdapter`) | Piecemeal patching against WB upstream is net-negative (the `e279c46` road-check attempt over-suppressed scenery elsewhere, reverted `677a726`); visible impact = a handful of trees a few meters off | The same WB-upstream class could hide a *larger* placement divergence elsewhere; revisit only via a coherent ACME-style per-vertex filter port | `CLandBlock::get_land_scenes`; ACME GameScene.cs:1074 per-vertex road filter |
|
||||
| AP-32 | Cell shells DRAW +0.02 m above the dat EnvCell origin (`ShellDrawLiftZ`, z-fight vs coplanar terrain); retail draws at the origin verbatim. Split invariant: PHYSICS + visibility graph UNLIFTED (f35cb8b, **#119**-residual), every DRAW-space consumer of portal/cell geometry LIFTED (OutsideView color gate via `Build(drawLiftZ)`, seal/punch fans — **#130**) | `src/AcDream.App/Rendering/GameWindow.cs:5604` (const at `PortalVisibilityBuilder.ShellDrawLiftZ`) | Shell floors coplanar with terrain z-fight in our z-buffered frame; the 2 cm lift is the documented stand-in | A new draw-space consumer of portal/cell polygons that forgets the lift re-opens a 2 cm seam at horizontal aperture edges (the #130 top-edge strip, ~7 px at 2.4 m); a visibility consumer that picks up the LIFTED transform re-opens the #119-residual horizontal-portal side-cull | retail draws cell geometry at the dat EnvCell origin (no lift) |
|
||||
| AP-33 | Interior-root look-in statics (**#124** sub-pass) draw WHOLE — no per-part viewcone check; retail viewconeCheck's each part vs the installed view. Look-in DYNAMICS are not drawn at all (deferred; retail draws objects per overlapped cell in the landscape stage) | `src/AcDream.App/Rendering/RetailPViewRenderer.cs` (`DrawBuildingLookIns`) | The main viewcone has no entries for look-in cells; over-include is the safe direction (z-correct, repainted outside apertures by the root's shells); look-in cell counts are small (~1-3 cells) | Statics: a few wasted draws only. Dynamics: an NPC inside a far building seen through two openings is invisible where retail shows it | `viewconeCheck` 0x0054c250; nested `DrawCells` objects pc:432878 |
|
||||
| AP-34 | Landscape-stage alpha deferral is a TWO-PHASE slice split (statics-early / dynamics+particles+weather-late around the **#124** look-ins), not retail's single deferred alpha flush. Residual: under OUTDOOR roots slice particles still draw before merged building interiors (the unreported outdoor sibling of **#131**/**#132**); building exteriors' own translucent batches draw early | `src/AcDream.App/Rendering/RetailPViewRenderer.cs` (`DrawLandscapeThroughOutsideView` late loop) | The MDI dispatcher draws translucency inside each Draw call; a faithful FlushAlphaList port needs a global deferred alpha list across all landscape draws — the split covers the interior-root cases the user can see (#131 portal swirl, #132 candle flame) | Translucent landscape content drawn early and screen-overlapped by content drawn later in the stage gets overpainted (no depth self-protection) — the portal-swirl/candle-flame class re-appears in the residual configurations | `D3DPolyRender::FlushAlphaList` (DrawCells pc:432722) |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue