fix(render) Campaign FW3 visual gate: candle flames pre-clear too
Second owner report at the same gate: candle-flame particles still invisible looking out. Flame emitters attach to STATIC owners (lamp and candle statics), and the walk path submitted the landscape-stage static-owner particle union AFTER the driver replay - post-clear, so the pre-clear drain never carried them and a later flush z-failed them at the sealed aperture. For an interior root the submission now runs at the walk pre-clear boundary (retail inserts each emitter during its cell landscape walk turn, before the clear+seals); outdoor roots keep the post-replay frame-end placement (#132). Interior cells own emitters stay in the final world scope where the walls already own depth. 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
f8fc21d467
commit
77fd40771b
1 changed files with 40 additions and 11 deletions
|
|
@ -510,8 +510,14 @@ public sealed class RetailPViewRenderer
|
|||
IRenderFrameEntityPassExecutor? capturedPasses = frameEntityPasses;
|
||||
InteriorEntityPartition.Result? capturedPartition = partition;
|
||||
ViewconeCuller capturedViewcone = viewcone;
|
||||
Walk.WalkFrameDriver capturedDriver = walkDriver!;
|
||||
_walkPreClearDynamics = () =>
|
||||
{
|
||||
// Retail inserts static-owner emitters (candle flames)
|
||||
// during their cells' landscape walk turns — submit
|
||||
// BEFORE the pre-clear drain so they composite against
|
||||
// still-true landscape depth, never the seals.
|
||||
SubmitWalkLandscapeStaticParticles(ctx, walkExecutor!, capturedDriver);
|
||||
passes.UseIndoorMembershipOnlyRouting();
|
||||
DrawLandscapeDynamicsPhase(
|
||||
ctx,
|
||||
|
|
@ -1243,20 +1249,19 @@ public sealed class RetailPViewRenderer
|
|||
/// routes it replaced used to ride, from the driver's own visited
|
||||
/// sets (plan §FW3 "FW3.2b-2 — the production rooting", items 2 and
|
||||
/// 4).</summary>
|
||||
private void DrawWalkDrivenStatics(
|
||||
/// <summary>The landscape-stage static-owner particle submission: the
|
||||
/// union of every outdoor-static record from a landscape cell the walk
|
||||
/// visited this frame, plus every shell record from a building the walk
|
||||
/// visited (plan §FW3 item 4 — retail gates particles per cell turn,
|
||||
/// <c>ShouldDrawParticles</c> @0x0050FE60, so this is MORE
|
||||
/// retail-faithful than the old per-slice sphere filter it replaced).
|
||||
/// Interior roots invoke this at the walk's pre-clear boundary; outdoor
|
||||
/// roots post-replay.</summary>
|
||||
private void SubmitWalkLandscapeStaticParticles(
|
||||
RetailPViewFrameInput ctx,
|
||||
RetailPViewPassExecutor passes,
|
||||
Walk.WalkFrameDriver driver)
|
||||
{
|
||||
var (frame, encoder) = passes.RequireWalkSubmission();
|
||||
driver.Replay(frame, encoder);
|
||||
|
||||
// Landscape-stage particle owners: the union of every outdoor-static
|
||||
// record from a landscape cell the walk visited this frame, plus
|
||||
// every shell record from a building the walk visited (plan §FW3
|
||||
// item 4 — retail gates particles per cell turn, ShouldDrawParticles
|
||||
// @0x0050FE60, so this is MORE retail-faithful than the old per-
|
||||
// slice sphere filter it replaces).
|
||||
_staticParticleUnionScratch.Clear();
|
||||
foreach (uint cellId in driver.VisitedLandscapeCellIds)
|
||||
UnionRecordOwners(_walkWorldData!.GetOutdoorStatics(cellId), _staticParticleUnionScratch);
|
||||
|
|
@ -1269,12 +1274,36 @@ public sealed class RetailPViewRenderer
|
|||
new RetailPViewLandscapeStaticParticleContext(_staticParticleUnionScratch));
|
||||
_staticParticleUnionScratch.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawWalkDrivenStatics(
|
||||
RetailPViewFrameInput ctx,
|
||||
RetailPViewPassExecutor passes,
|
||||
Walk.WalkFrameDriver driver)
|
||||
{
|
||||
var (frame, encoder) = passes.RequireWalkSubmission();
|
||||
driver.Replay(frame, encoder);
|
||||
|
||||
// Landscape-stage static-owner particles (candle flames on lamp and
|
||||
// candle statics): for an OUTDOOR root they submit here, post-replay
|
||||
// (drained at the frame-end flush over finished depth — the #132
|
||||
// placement). For an INTERIOR root they must submit at the walk's
|
||||
// PRE-CLEAR boundary instead — retail inserts each one during its
|
||||
// cell's landscape walk turn, before the clear+seals; a post-seal
|
||||
// drain z-fails them at the aperture (the visual-gate "no candle
|
||||
// flames looking out" report) — so SubmitWalkLandscapeStaticParticles
|
||||
// is invoked from _walkPreClearDynamics in that case, and skipped
|
||||
// here.
|
||||
if (ctx.RootCell.IsOutdoorNode)
|
||||
SubmitWalkLandscapeStaticParticles(ctx, passes, driver);
|
||||
|
||||
// Cell-stage particle owners for the interior root's OWN flood cells
|
||||
// (non-look-in — the walk draws their statics too, via
|
||||
// OnInteriorFloodDrawTurn/EmitCellTurn, so the retired CellStatic
|
||||
// route's cell-particle submission needs the same re-sourcing).
|
||||
// Look-in cells get their OWN per-cell union in
|
||||
// These stay POST-replay: interior emitters draw in the final world
|
||||
// scope where the cell walls already own depth (retail's cell-walk
|
||||
// insertion). Look-in cells get their OWN per-cell union in
|
||||
// DrawBuildingLookInDynamics so a static owner is never submitted
|
||||
// twice.
|
||||
_cellParticleOwnerScratch.Clear();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue