Lands the working A8 indoor-rendering and streaming fixes accumulated this session. User has verified these visually to some degree (e.g. lifestone / translucent meshes confirmed fine under the FrontFace flip; bridge / wall / collision regressions confirmed fixed after travel); not every path has been exhaustively gated. The cellar-flap defect remains OPEN and will be solved the retail-faithful way via a dedicated brainstorm (see handoff docs). Rendering core (reviewed, high confidence): - EnvCellRenderer SSBO stride fix: upload packed Matrix4x4[] (64B) instead of the 80B CPU InstanceData struct the shader never expected — fixes the transform/texture "explosion" for any draw with >1 instance (cells that dedupe to a shared cellGeomId). Real root cause. - WB-style global FrontFace(CW) + per-batch CullMode carried through the MDI layout (GroupKey + BuildIndirectArrays + DrawIndirectRange split into same-cull runs with absolute uDrawIDOffset per run). - EntitySet partitioning (IndoorPass / OutdoorScenery / LiveDynamic) + WorldEntity.BuildingShellAnchorCellId so building shells scope to their dat-derived building cell instead of rendering everywhere. - RenderOutsideInAcdream (look into buildings from outside) + CollectVisiblePortalBuildings frustum cull of portal bounds. - Sky-when-inside-building + per-cell audit probe + GL-state probe. Streaming / perf (test-covered; not independently code-reviewed this session): - Near/far priority queues so near work wins over far; PromoteToNear carries full landblock + mesh data; LandblockEntriesWithoutAnimatedIndex avoids rebuilding the animated-lookup dict in the hot draw path. Fixes the bridge-not-appearing / missing-walls / broken-collision-after-travel regressions and improves post-transition FPS. Tooling + docs: - tools/A8CellAudit: offline dat cell/portal/building dumper (portals + buildings modes) — reproduces the cellar-flap investigation with no launch. - docs/research cellar-flap root-cause + option-2 handoff (the didInsideStencil double-duty finding + the WB-recursive design decision + brainstorm prompt), entity-taxonomy, replan, issue-78 visibility investigation. Diagnostics retained on purpose: ACDREAM_A8_DIAG_* gates, portal_stencil.vert provisional pos.w clamp, and the probe families are kept (env-var gated, zero cost when off) because the pending option-2 cellar-flap brainstorm needs them. Strip in the option-2 ship commit. Indoor branch stays behind ACDREAM_A8_INDOOR_BRANCH=1 (default off = pre-A8 visual). Build green; App tests + Core (streaming/dispatcher/loader) tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.9 KiB
Phase A8 Cellar-Flap Handoff - 2026-05-28
Status
The remaining cottage/cellar artifact is still visible. The user sees a short-lived green terrain-like rectangle/flap over the cellar entrance or floor opening when entering/exiting a building and when the chase camera angle changes.
This thread hit the project rule: 3 visual-gated fixes failed for this specific artifact. Stop here. Do not ship a fourth speculative renderer change. The next step must be source-provenance instrumentation or an architecture comparison.
The client was stopped after the failed visual gate to avoid build/file locks.
Last Good Context
The broader A8 indoor renderer is much improved and shippable aside from this artifact:
- Theory A front-face alignment plus per-batch
CullModefixed major missing/inside-out geometry. - The
InstanceDatastride fix explained the texture explosion/distortion root cause. - Building shell scoping, portal bounds, streaming/promotion fixes, and FPS fixes remain important.
- The current artifact is narrow: a green terrain-like flap at/near cellar entrance transitions.
Failed Fixes In This Micro-Loop
1. Camera branch gate relaxation
Hypothesis: strict PointInCell camera-inside-building gating was causing the renderer to switch branches while the chase camera crossed walls/portals.
Change tried: allow the inside-out branch to continue based on CameraCell.BuildingId, without the strict PointInCell check.
Result: visual gate failed. User still saw the artifact. Change was reverted back to strict PointInCell.
Evidence ruled out: the artifact is not solely caused by the render branch dropping out when the camera is slightly outside the cell.
2. Portal stencil pos.w clamp
Hypothesis: near-zero clip W for portal stencil triangles was exploding the screen-space mask as the camera crossed a portal plane.
Change tried: restored WorldBuilder-style clamp in src/AcDream.App/Rendering/Shaders/portal_stencil.vert:
vec4 pos = uViewProjection * vec4(aPosition, 1.0);
if (abs(pos.w) < 0.001)
pos.w = pos.w < 0.0 ? -0.001 : 0.001;
gl_Position = pos;
Result: visual gate failed. User still saw the artifact.
Interpretation: this may still be WB parity and may be worth keeping, but it is not the root cause of the cellar flap.
3. Visible-cell portal mask
Hypothesis: RenderInsideOutAcdream was punching outdoor terrain through all exit portals in the camera building, not just exits reached by the current portal traversal. A window/door portal could project over the cellar opening and let terrain draw through it.
Changes tried:
- Added
CellVisibility.TryGetCell(uint, out LoadedCell?). - Added
IndoorCellStencilPipeline.DrawUploadedPortalMesh(...)to draw the already-uploaded visible-cell portal mesh. - Changed
RenderInsideOutAcdreamStep 1/2 to upload portal triangles fromvisibleCellIds, notcamBuildings. - Wrapped Step 4 terrain/outdoor scenery draw inside
if (didInsideStencil). - Added pure math test
BuildTriangles_OnlyIncludesProvidedVisibleCells.
Verification before launch:
dotnet build src\AcDream.App\AcDream.App.csproj -c Debug --no-restore
dotnet test tests\AcDream.App.Tests\AcDream.App.Tests.csproj -c Debug --filter FullyQualifiedName~IndoorCellStencilPipelineTests --no-restore
Both passed after shutting down build servers. The first parallel test attempt only failed because VBCSCompiler locked AcDream.App.dll while a parallel build was running.
Visual result: failed. User still saw the flap.
Evidence ruled out: the artifact is not explained only by building-wide vs visible-cell exit portal masking.
Current Uncommitted Changes From This Micro-Loop
These are not visually validated as a fix:
src/AcDream.App/Rendering/Shaders/portal_stencil.vert- WB-style
pos.wclamp.
- WB-style
src/AcDream.App/Rendering/CellVisibility.csTryGetCell.
src/AcDream.App/Rendering/IndoorCellStencilPipeline.csDrawUploadedPortalMesh.
src/AcDream.App/Rendering/GameWindow.cs- visible-cell portal mask in
RenderInsideOutAcdream. - Step 4 fail-closed when no portal mesh uploaded.
- visible-cell portal mask in
tests/AcDream.App.Tests/Rendering/IndoorCellStencilPipelineTests.cs- visible-cell-only triangle generation test.
Do not commit these as "the fix" unless a later source-provenance check proves they are correct and harmless. If the next architecture route goes elsewhere, revert or split them honestly.
What We Know About The Cellar Entrance
Prior inspection found:
- The cellar transition around Holtburg cottage cells
0xA9B40143 -> 0x0146 -> 0x0147is indoor-to-indoor. - The relevant transition portals are not literal
OtherCellId == 0xFFFFoutside exits. - The portal cap polygons inspected there are
NoPos. - That made "cell mesh uploads the outdoor floor polygon" unlikely, but not proven impossible for the visible green patch.
What The Failed Fixes Suggest
The green pixels may not be caused by the portal mask at all. We need to prove which render pass writes them before touching behavior again.
Candidate explanations now:
-
The green patch is not Step 4 terrain. It could be an EnvCell surface with the wrong texture/material, stale texture binding, or an indoor static object surface resolving to a grass texture.
-
The patch is Step 4 terrain, but the stencil/depth mask source is not the exit portal list. It may be a stale stencil/depth state leak, a Step 3/4 depth ordering issue, or a missing retail occlusion/scissor lifecycle detail.
-
The cellar opening has a missing or late-loaded indoor object. If a hatch/stair/floor object should cover or occlude that area and is missing for one or more frames, outdoor/terrain pixels behind it become visible.
-
Camera clipping is exposing an intentionally hidden surface. Retail camera collision is incomplete in acdream. If the camera clips through the wall/floor volume, the renderer may be showing a view retail never permits. This does not explain all cases by itself, because the user also sees it during transitions, but it must be separated from a renderer bug.
Next Step - Evidence Only
Add a provenance diagnostic, not a fix. One visual launch should answer what writes the green flap.
Recommended diagnostic:
- Add an env-gated pass tint or disable switch for only the inside-out Step 4 terrain draw.
- Add a separate tint/disable for Step 4
OutdoorScenery. - Add a tint/disable for Step 3 EnvCell opaque.
- Keep default behavior unchanged.
Example env names:
ACDREAM_A8_DIAG_DISABLE_INSIDE_STEP4_TERRAIN=1
ACDREAM_A8_DIAG_DISABLE_INSIDE_STEP4_OUTDOOR=1
ACDREAM_A8_DIAG_DISABLE_INSIDE_ENVCELL_OPAQUE=1
Run only one diagnostic at a time:
- If disabling Step 4 terrain removes the green flap, the issue is still terrain leaking through the indoor view mask.
- If disabling Step 4 terrain does not remove it, stop looking at portal exits and inspect EnvCell/static texture/material assignment for the specific surface.
- If disabling EnvCell opaque removes it, dump the exact
CellStructpolygon/material under the camera/screenshot area.
Do not ship the diagnostic switches. Strip them after the source is known.
Launch/Test Notes
Last clean visual launch:
$env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call"
$env:ACDREAM_LIVE = "1"
$env:ACDREAM_TEST_HOST = "127.0.0.1"
$env:ACDREAM_TEST_PORT = "9000"
$env:ACDREAM_TEST_USER = "testaccount"
$env:ACDREAM_TEST_PASS = "testpassword"
$env:ACDREAM_A8_INDOOR_BRANCH = "1"
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug
The log files from the last launch were empty because this was a clean no-probe run:
a8-visible-cell-portalmask-cellar-flap-20260528-161702.out.loga8-visible-cell-portalmask-cellar-flap-20260528-161702.err.log
Stop Rule
This artifact has now consumed three visual failures in this micro-loop. Next session should not make another fix until it has hard evidence identifying the pass/polygon/source texture responsible for the green pixels.