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
|
// Campaign FW3.2b-2: the walk's production world-data registries
|
||||||
// (published/retired by LandblockRenderPublisher) plus the per-frame
|
// (published/retired by LandblockRenderPublisher) plus the per-frame
|
||||||
// driver state. Null until the composition passes them; the static
|
// driver state. Null until the composition passes them; the static
|
||||||
|
|
@ -300,6 +307,16 @@ public sealed class RetailPViewRenderer
|
||||||
|
|
||||||
Action clearInteriorDepth = () =>
|
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
|
// Retail PView::DrawCells 0x005A4872 drains the landscape
|
||||||
// alpha list immediately before the gated full depth clear —
|
// alpha list immediately before the gated full depth clear —
|
||||||
// mirrors DrawLandscapeThroughOutsideView's own pre-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
|
// feed the surviving dynamic routes only (plan §FW3 item 1's
|
||||||
// dual-compute split). Campaign FW3.4a: the walk itself
|
// dual-compute split). Campaign FW3.4a: the walk itself
|
||||||
// already ran (Collect, above) — this is Replay only.
|
// already ran (Collect, above) — this is Replay only.
|
||||||
DrawWalkDrivenStatics(ctx, walkExecutor!, walkDriver!);
|
//
|
||||||
passes.UseIndoorMembershipOnlyRouting();
|
// FW3 visual-gate fix: for an INTERIOR root the dynamics
|
||||||
DrawLandscapeDynamicsPhase(
|
// phase (outside dynamics + look-in dynamics + outdoor
|
||||||
ctx,
|
// particles + weather) must draw at the walk's PRE-CLEAR
|
||||||
passes,
|
// boundary — retail draws them inside LScape::draw, before
|
||||||
clipAssembly,
|
// the clear+seals — so the driver's clearInteriorDepth
|
||||||
partition,
|
// closure invokes it via _walkPreClearDynamics. For an
|
||||||
viewcone,
|
// OUTDOOR root there is no clear (retail has none) and the
|
||||||
frameEntityPasses,
|
// phase runs after the driver, matching the old order.
|
||||||
in frameView);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue