fix(render) Campaign FW3 visual gate: interior dynamics draw PRE-clear
Owner gate report (Holtburg, looking out from a house): no doors on buildings, no candle particles, the character vanishing for a frame when crossing out. One family: the cutover moved the interior depth clear + exit seals into the walk turn, but the dynamics phase (outside dynamics, look-in dynamics, outdoor particles, weather) still ran AFTER the whole walk - everything beyond the door plane z-failed against the seals stamp, the exact #118 house-exit clip+vanish class the old code documented. Retail draws the outside world's objects INSIDE LScape::draw, strictly before the clear+seals. The driver's clearInteriorDepth closure now invokes the dynamics phase at that pre-clear boundary for interior roots (_walkPreClearDynamics, assigned around the Replay, cleared in finally); outdoor roots keep the post-driver order (no clear exists there). Packed route consumption order is unchanged (LookInObject -> LandscapeOutsideDynamic -> DynamicLast). Suites: full Release build 0 warnings; hermetic 6,758/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
806f87ab79
commit
f8fc21d467
1 changed files with 62 additions and 10 deletions
|
|
@ -93,6 +93,13 @@ public sealed class RetailPViewRenderer
|
|||
{
|
||||
}
|
||||
|
||||
// FW3 visual-gate fix: the interior root's dynamics phase, invoked by
|
||||
// the driver's clearInteriorDepth closure at the walk's pre-clear
|
||||
// boundary (retail draws outside objects inside LScape::draw, before
|
||||
// the clear+seals). Assigned per frame around the Replay, always
|
||||
// cleared in finally.
|
||||
private Action? _walkPreClearDynamics;
|
||||
|
||||
// Campaign FW3.2b-2: the walk's production world-data registries
|
||||
// (published/retired by LandblockRenderPublisher) plus the per-frame
|
||||
// driver state. Null until the composition passes them; the static
|
||||
|
|
@ -300,6 +307,16 @@ public sealed class RetailPViewRenderer
|
|||
|
||||
Action clearInteriorDepth = () =>
|
||||
{
|
||||
// FW3 visual-gate fix (owner report: doors/candles invisible
|
||||
// looking out; the crossing vanish): retail draws the
|
||||
// OUTSIDE world's objects INSIDE LScape::draw — strictly
|
||||
// BEFORE the depth clear + seals (the #118 house-exit
|
||||
// clip+vanish lesson: anything drawn after the seals z-fails
|
||||
// against their true-depth stamp the moment it stands beyond
|
||||
// the door plane). The surviving dynamic routes + outdoor
|
||||
// particles + weather therefore run HERE, at the walk's
|
||||
// pre-clear boundary, for an interior root.
|
||||
_walkPreClearDynamics?.Invoke();
|
||||
// Retail PView::DrawCells 0x005A4872 drains the landscape
|
||||
// alpha list immediately before the gated full depth clear —
|
||||
// mirrors DrawLandscapeThroughOutsideView's own pre-clear
|
||||
|
|
@ -480,16 +497,51 @@ public sealed class RetailPViewRenderer
|
|||
// feed the surviving dynamic routes only (plan §FW3 item 1's
|
||||
// dual-compute split). Campaign FW3.4a: the walk itself
|
||||
// already ran (Collect, above) — this is Replay only.
|
||||
DrawWalkDrivenStatics(ctx, walkExecutor!, walkDriver!);
|
||||
passes.UseIndoorMembershipOnlyRouting();
|
||||
DrawLandscapeDynamicsPhase(
|
||||
ctx,
|
||||
passes,
|
||||
clipAssembly,
|
||||
partition,
|
||||
viewcone,
|
||||
frameEntityPasses,
|
||||
in frameView);
|
||||
//
|
||||
// FW3 visual-gate fix: for an INTERIOR root the dynamics
|
||||
// phase (outside dynamics + look-in dynamics + outdoor
|
||||
// particles + weather) must draw at the walk's PRE-CLEAR
|
||||
// boundary — retail draws them inside LScape::draw, before
|
||||
// the clear+seals — so the driver's clearInteriorDepth
|
||||
// closure invokes it via _walkPreClearDynamics. For an
|
||||
// OUTDOOR root there is no clear (retail has none) and the
|
||||
// phase runs after the driver, matching the old order.
|
||||
RenderFrameView capturedView = frameView;
|
||||
IRenderFrameEntityPassExecutor? capturedPasses = frameEntityPasses;
|
||||
InteriorEntityPartition.Result? capturedPartition = partition;
|
||||
ViewconeCuller capturedViewcone = viewcone;
|
||||
_walkPreClearDynamics = () =>
|
||||
{
|
||||
passes.UseIndoorMembershipOnlyRouting();
|
||||
DrawLandscapeDynamicsPhase(
|
||||
ctx,
|
||||
passes,
|
||||
clipAssembly,
|
||||
capturedPartition,
|
||||
capturedViewcone,
|
||||
capturedPasses,
|
||||
in capturedView);
|
||||
};
|
||||
try
|
||||
{
|
||||
DrawWalkDrivenStatics(ctx, walkExecutor!, walkDriver!);
|
||||
passes.UseIndoorMembershipOnlyRouting();
|
||||
if (ctx.RootCell.IsOutdoorNode)
|
||||
{
|
||||
DrawLandscapeDynamicsPhase(
|
||||
ctx,
|
||||
passes,
|
||||
clipAssembly,
|
||||
partition,
|
||||
viewcone,
|
||||
frameEntityPasses,
|
||||
in frameView);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_walkPreClearDynamics = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue