feat(render): R1 — binary render decision, indoor = per-cell DrawInside only
GameWindow.OnRender: when clipRoot != null, run only InteriorRenderer.DrawInside (per-cell shells + per-cell objects + live-dynamics); the global entity pass + global shell pass are no longer issued indoors. Outdoor scenery drawn clipped to the doorway (after terrain, before the Z-clear). Outdoor root path unchanged. pvFrame hoisted so the splice reads OrderedVisibleCells; per-frame 3-bucket partition built on the indoor root. Retail RenderNormalMode @ 0x453aa0. InteriorRenderer amended with a DrawableCells membership filter (an IsNothingVisible cell can be in OrderedVisibleCells but absent from CellIdToSlot — iterate for ORDER, filter for membership; matches the old envCellShellFilter set exactly). Build green, 174/174 App tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4b75c68ea3
commit
c4fd71149a
2 changed files with 72 additions and 26 deletions
|
|
@ -11,6 +11,12 @@ public sealed class InteriorRenderContext
|
|||
/// <summary>Visible cells, closest-first (retail cell_draw_list). From PortalVisibilityFrame.</summary>
|
||||
public required IReadOnlyList<uint> OrderedVisibleCells { get; init; }
|
||||
|
||||
/// <summary>The cells the assembler mapped a clip slot for (ClipFrameAssembly.CellIdToSlot.Keys =
|
||||
/// the GameWindow envCellShellFilter). A cell may appear in <see cref="OrderedVisibleCells"/> but
|
||||
/// reduce to IsNothingVisible in the assembler (no slot) — those are skipped. This is the
|
||||
/// membership filter; <see cref="OrderedVisibleCells"/> supplies the draw ORDER.</summary>
|
||||
public required IReadOnlySet<uint> DrawableCells { get; init; }
|
||||
|
||||
/// <summary>The 3-bucket entity split (<see cref="InteriorEntityPartition"/>). Only ByCell +
|
||||
/// LiveDynamic are used here; Outdoor scenery is drawn by the caller's landscape-through-door
|
||||
/// step (clipped to OutsideView).</summary>
|
||||
|
|
@ -54,6 +60,7 @@ public sealed class InteriorRenderer
|
|||
// Loop A — per-cell OPAQUE shell + that cell's static objects (closest-first).
|
||||
foreach (uint cellId in ctx.OrderedVisibleCells)
|
||||
{
|
||||
if (!ctx.DrawableCells.Contains(cellId)) continue; // no clip slot ⇒ assembler culled it
|
||||
_oneCell.Clear();
|
||||
_oneCell.Add(cellId);
|
||||
_envCells.Render(WbRenderPass.Opaque, _oneCell);
|
||||
|
|
@ -70,6 +77,7 @@ public sealed class InteriorRenderer
|
|||
// Loop B — per-cell TRANSPARENT shells (stained glass / additive cell surfaces).
|
||||
foreach (uint cellId in ctx.OrderedVisibleCells)
|
||||
{
|
||||
if (!ctx.DrawableCells.Contains(cellId)) continue;
|
||||
_oneCell.Clear();
|
||||
_oneCell.Add(cellId);
|
||||
_envCells.Render(WbRenderPass.Transparent, _oneCell);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue