fix(rendering): synchronize hidden live projections
Inbound state continues while portal reveal blocks ordinary world simulation. Synchronize only the derived render projection after those hidden-frame network and command phases so the first revealed draw cannot observe a stale live transform, without advancing effects, particles, attachments, or lights.
This commit is contained in:
parent
528dec6072
commit
6a026c5ab0
6 changed files with 52 additions and 4 deletions
|
|
@ -517,7 +517,8 @@ internal sealed class FrameRootCompositionPhase
|
|||
session.LiveSession,
|
||||
session.LocalPlayerFrame,
|
||||
session.LiveSpatialReconciler,
|
||||
live.WorldAvailability);
|
||||
live.WorldAvailability,
|
||||
live.RenderSceneShadow?.LiveProjections);
|
||||
var cameraFrame = new CameraFrameController(
|
||||
host.CameraController,
|
||||
d.InputCapture,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
using AcDream.App.Update;
|
||||
using AcDream.App.World;
|
||||
using AcDream.Core.World;
|
||||
|
||||
namespace AcDream.App.Rendering.Scene;
|
||||
|
||||
internal interface ILiveRenderProjectionSink
|
||||
internal interface ILiveRenderProjectionSink : IRenderProjectionSyncPhase
|
||||
{
|
||||
bool OnEntityReady(LiveEntityReadyCandidate candidate);
|
||||
void OnProjectionVisibilityChanged(LiveEntityRecord record, bool visible);
|
||||
void OnProjectionPoseReady(uint serverGuid);
|
||||
void OnProjectionRemoved(uint localEntityId);
|
||||
void OnResourceUnregister(WorldEntity entity);
|
||||
void SynchronizeActiveSources();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,17 @@ internal interface ILiveSpatialReconcilePhase
|
|||
void Reconcile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keeps the derived render projection synchronized after inbound mutation
|
||||
/// while normal world simulation/presentation is blocked by portal reveal.
|
||||
/// This is deliberately narrower than full spatial reconciliation: hidden
|
||||
/// frames must not advance particles, effects, attachments, or lights.
|
||||
/// </summary>
|
||||
internal interface IRenderProjectionSyncPhase
|
||||
{
|
||||
void SynchronizeActiveSources();
|
||||
}
|
||||
|
||||
internal interface IParticleRangeSource
|
||||
{
|
||||
float RangeMultiplier { get; }
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ internal sealed class RetailLiveFrameCoordinator : IRetailLiveFramePhase
|
|||
private readonly IPostNetworkCommandFramePhase _localPlayer;
|
||||
private readonly ILiveSpatialReconcilePhase _spatialReconciler;
|
||||
private readonly IWorldGenerationAvailability _availability;
|
||||
private readonly IRenderProjectionSyncPhase? _renderProjectionSync;
|
||||
|
||||
public RetailLiveFrameCoordinator(
|
||||
ILiveObjectFramePhase objects,
|
||||
|
|
@ -32,7 +33,8 @@ internal sealed class RetailLiveFrameCoordinator : IRetailLiveFramePhase
|
|||
ILiveSessionFramePhase session,
|
||||
IPostNetworkCommandFramePhase localPlayer,
|
||||
ILiveSpatialReconcilePhase spatialReconciler,
|
||||
IWorldGenerationAvailability? availability = null)
|
||||
IWorldGenerationAvailability? availability = null,
|
||||
IRenderProjectionSyncPhase? renderProjectionSync = null)
|
||||
{
|
||||
_objects = objects ?? throw new ArgumentNullException(nameof(objects));
|
||||
_worldState = worldState ?? throw new ArgumentNullException(nameof(worldState));
|
||||
|
|
@ -41,6 +43,7 @@ internal sealed class RetailLiveFrameCoordinator : IRetailLiveFramePhase
|
|||
_spatialReconciler = spatialReconciler
|
||||
?? throw new ArgumentNullException(nameof(spatialReconciler));
|
||||
_availability = availability ?? AlwaysAvailableWorldGeneration.Instance;
|
||||
_renderProjectionSync = renderProjectionSync;
|
||||
}
|
||||
|
||||
public void Tick(float deltaSeconds)
|
||||
|
|
@ -53,6 +56,8 @@ internal sealed class RetailLiveFrameCoordinator : IRetailLiveFramePhase
|
|||
_localPlayer.RunPostNetworkCommandPhase();
|
||||
if (_availability.IsWorldAvailable)
|
||||
_spatialReconciler.Reconcile();
|
||||
else
|
||||
_renderProjectionSync?.SynchronizeActiveSources();
|
||||
}
|
||||
|
||||
public static double NormalizeDeltaSeconds(double deltaSeconds) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue