feat(rendering): journal static scene projections

Append exact static and EnvCell-shell projection deltas only at committed spatial activation and detach receipts. Same-landblock rehydrate now reconciles retained, new, and omitted presentation identities without constructing or drawing the shadow scene in production.

Co-authored-by: Erik Nilsson <erikn@users.noreply.github.com>
This commit is contained in:
Erik 2026-07-24 21:57:33 +02:00
parent dbd8318417
commit 5d19c56d15
10 changed files with 997 additions and 10 deletions

View file

@ -333,6 +333,7 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
_world.Set(entry.Entity, record.Transform);
_world.Set(entry.Entity, record.Bounds);
_world.Set(entry.Entity, record.SortKey);
_world.Set(entry.Entity, record.Source);
OrDirty(
entry.Entity,
RenderDirtyMask.Transform
@ -343,14 +344,17 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
_world.Set(entry.Entity, record.MeshSet);
_world.Set(entry.Entity, record.Material);
_world.Set(entry.Entity, record.DegradeState);
_world.Set(entry.Entity, record.Source);
OrDirty(entry.Entity, RenderDirtyMask.Appearance);
break;
case RenderProjectionDeltaKind.UpdateFlags:
_world.Set(entry.Entity, record.Flags);
_world.Set(entry.Entity, record.Source);
OrDirty(entry.Entity, RenderDirtyMask.Flags);
break;
case RenderProjectionDeltaKind.Rebucket:
_world.Set(entry.Entity, record.Residency);
_world.Set(entry.Entity, record.Source);
OrDirty(entry.Entity, RenderDirtyMask.SpatialResidency);
break;
default:
@ -430,6 +434,7 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
record.SortKey,
record.OwnerIncarnation,
record.DirtyMask,
record.Source,
tag);
private void WriteRecord(
@ -447,6 +452,7 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
_world.Set(entity, record.SortKey);
_world.Set(entity, record.OwnerIncarnation);
_world.Set(entity, record.DirtyMask);
_world.Set(entity, record.Source);
}
private RenderProjectionRecord ReadRecord(in SceneEntry entry) =>
@ -463,7 +469,8 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
_world.Get<RenderProjectionFlags>(entry.Entity),
_world.Get<RenderDegradeState>(entry.Entity),
_world.Get<RenderSortKey>(entry.Entity),
_world.Get<RenderDirtyMask>(entry.Entity));
_world.Get<RenderDirtyMask>(entry.Entity),
_world.Get<RenderSourceMetadata>(entry.Entity));
private void Destroy(in SceneEntry entry)
{
@ -549,6 +556,9 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
hash.Add(record.Id.RawValue);
hash.Add((byte)record.ProjectionClass);
hash.Add(record.OwnerIncarnation.RawValue);
hash.Add(record.Transform.Position);
hash.Add(record.Transform.Rotation);
hash.Add(record.Transform.UniformScale);
hash.Add(record.Transform.LocalToWorld);
hash.Add(record.PreviousTransform.LocalToWorld);
hash.Add(record.MeshSet.Handle.RawValue);
@ -566,6 +576,18 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
hash.Add(record.DegradeState.Level);
hash.Add(record.DegradeState.Revision);
hash.Add(record.SortKey.Value);
hash.Add(record.Source.LocalEntityId);
hash.Add(record.Source.ServerGuid);
hash.Add(record.Source.SourceId);
hash.Add(record.Source.ParentCellId);
hash.Add(record.Source.EffectCellId);
hash.Add(record.Source.BuildingShellAnchorCellId);
hash.Add(record.Source.TransformFingerprint.Low);
hash.Add(record.Source.TransformFingerprint.High);
hash.Add(record.Source.GeometryFingerprint.Low);
hash.Add(record.Source.GeometryFingerprint.High);
hash.Add(record.Source.AppearanceFingerprint.Low);
hash.Add(record.Source.AppearanceFingerprint.High);
}
private readonly record struct ProjectionIdentity(RenderProjectionId Id);