refactor(render): remove the production portal frame carrier
This commit is contained in:
parent
69e69408e8
commit
cb22691beb
10 changed files with 128 additions and 443 deletions
|
|
@ -1,9 +1,9 @@
|
|||
// ClipFrameAssembler.cs
|
||||
//
|
||||
// Retail PView assembly policy. PortalVisibilityBuilder produces a retail-like
|
||||
// view graph: one portal_view list per visible cell plus an outside_view list.
|
||||
// This assembler packs each visible polygon as an individual GPU clip slot so
|
||||
// the renderer can draw the exact PView order:
|
||||
// Retail view assembly policy. The production frame walk supplies its
|
||||
// outside_view directly; the legacy PortalVisibilityBuilder overload remains
|
||||
// only for isolated research/replay tests. Each visible polygon is packed as
|
||||
// an individual GPU clip slot.
|
||||
//
|
||||
// outside_view landscape slices
|
||||
// reverse cell_draw_list exit masks
|
||||
|
|
@ -40,15 +40,7 @@ public enum TerrainClipMode
|
|||
public readonly record struct ClipViewSlice(int Slot, Vector4 NdcAabb, Vector4[] Planes);
|
||||
|
||||
/// <summary>
|
||||
/// Identifies one cell inside one nested building look-in. The same EnvCell can
|
||||
/// be reached by more than one building PView, so a cell id alone is not a
|
||||
/// sufficient routing key.
|
||||
/// </summary>
|
||||
public readonly record struct LookInClipCell(int FrameIndex, uint CellId);
|
||||
|
||||
/// <summary>
|
||||
/// Result of <see cref="ClipFrameAssembler.Assemble"/>: populated clip buffers
|
||||
/// plus routing data consumed by the render orchestration.
|
||||
/// Populated clip buffers plus routing data consumed by the render walk.
|
||||
/// </summary>
|
||||
public sealed class ClipFrameAssembly
|
||||
{
|
||||
|
|
@ -64,12 +56,6 @@ public sealed class ClipFrameAssembly
|
|||
/// <summary>Full retail portal_view slices per visible cell.</summary>
|
||||
public Dictionary<uint, ClipViewSlice[]> CellIdToViewSlices { get; } = new();
|
||||
|
||||
/// <summary>First drawable slice slot per nested look-in cell.</summary>
|
||||
public Dictionary<LookInClipCell, int> LookInCellToSlot { get; } = new();
|
||||
|
||||
/// <summary>All retail portal_view slices per nested look-in cell.</summary>
|
||||
public Dictionary<LookInClipCell, ClipViewSlice[]> LookInCellToViewSlices { get; } = new();
|
||||
|
||||
/// <summary>Full retail outside_view slices.</summary>
|
||||
public ClipViewSlice[] OutsideViewSlices { get; private set; } = System.Array.Empty<ClipViewSlice>();
|
||||
|
||||
|
|
@ -106,8 +92,6 @@ public sealed class ClipFrameAssembly
|
|||
Frame = frame;
|
||||
foreach (ClipViewSlice[] slices in CellIdToViewSlices.Values)
|
||||
ReturnSlices(slices);
|
||||
foreach (ClipViewSlice[] slices in LookInCellToViewSlices.Values)
|
||||
ReturnSlices(slices);
|
||||
foreach (int[] slots in CellIdToViewSlots.Values)
|
||||
ReturnSlots(slots);
|
||||
if (OutsideViewSlices.Length != 0)
|
||||
|
|
@ -116,8 +100,6 @@ public sealed class ClipFrameAssembly
|
|||
CellIdToSlot.Clear();
|
||||
CellIdToViewSlots.Clear();
|
||||
CellIdToViewSlices.Clear();
|
||||
LookInCellToSlot.Clear();
|
||||
LookInCellToViewSlices.Clear();
|
||||
PerCellPlaneCounts.Clear();
|
||||
OutsideViewSlices = System.Array.Empty<ClipViewSlice>();
|
||||
SliceScratch.Clear();
|
||||
|
|
@ -272,6 +254,53 @@ public sealed class ClipFrameAssembly
|
|||
|
||||
public static class ClipFrameAssembler
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts one production walk assembly without constructing a parallel
|
||||
/// PortalVisibilityFrame. Outdoor roots begin with retail's full-screen
|
||||
/// default view; interior roots begin empty and are populated from
|
||||
/// <see cref="Walk.RetailFrameWalk.InteriorOutsideView"/> after Collect.
|
||||
/// </summary>
|
||||
public static ClipFrameAssembly BeginWalkFrame(
|
||||
ClipFrame frame,
|
||||
bool outdoorRoot,
|
||||
ClipFrameAssembly? reuseAssembly = null)
|
||||
{
|
||||
System.ArgumentNullException.ThrowIfNull(frame);
|
||||
frame.Reset();
|
||||
ClipFrameAssembly assembly = reuseAssembly ?? new ClipFrameAssembly();
|
||||
assembly.Reset(frame);
|
||||
|
||||
if (outdoorRoot)
|
||||
{
|
||||
List<ClipViewSlice> slices = assembly.SliceScratch;
|
||||
slices.Clear();
|
||||
var fullScreen = new Vector4(-1f, -1f, 1f, 1f);
|
||||
slices.Add(new ClipViewSlice(0, fullScreen, System.Array.Empty<Vector4>()));
|
||||
assembly.SetOutsideViewSlices(assembly.CopySlices(slices));
|
||||
assembly.OutdoorSlot = 0;
|
||||
assembly.OutdoorVisible = true;
|
||||
assembly.TerrainMode = TerrainClipMode.Scissor;
|
||||
assembly.TerrainScissorNdcAabb = fullScreen;
|
||||
assembly.HasOutsideView = true;
|
||||
assembly.OutsideViewNdcAabb = fullScreen;
|
||||
assembly.OutsidePlaneCount = 0;
|
||||
assembly.ScissorFallbacks = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assembly.OutdoorSlot = 0;
|
||||
assembly.OutdoorVisible = false;
|
||||
assembly.TerrainMode = TerrainClipMode.Skip;
|
||||
assembly.TerrainScissorNdcAabb = Vector4.Zero;
|
||||
assembly.HasOutsideView = false;
|
||||
assembly.OutsideViewNdcAabb = Vector4.Zero;
|
||||
assembly.OutsidePlaneCount = 0;
|
||||
assembly.ScissorFallbacks = 0;
|
||||
}
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
public static ClipFrameAssembly Assemble(
|
||||
ClipFrame frame,
|
||||
PortalVisibilityFrame pvFrame,
|
||||
|
|
@ -529,70 +558,6 @@ public static class ClipFrameAssembler
|
|||
assembly.ScissorFallbacks = scissorFallbacks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the cell views used by nested <c>DrawBuilding -> DrawPortal</c>
|
||||
/// PViews to the already assembled frame. Retail installs each nested
|
||||
/// cell's own <c>portal_view</c> before drawing its shell and object list;
|
||||
/// these slots must therefore be published with the main frame before the
|
||||
/// first draw is recorded.
|
||||
/// </summary>
|
||||
public static void AppendLookInFrames(
|
||||
ClipFrame frame,
|
||||
IReadOnlyList<PortalVisibilityFrame> lookInFrames,
|
||||
ClipFrameAssembly assembly)
|
||||
{
|
||||
System.ArgumentNullException.ThrowIfNull(frame);
|
||||
System.ArgumentNullException.ThrowIfNull(lookInFrames);
|
||||
System.ArgumentNullException.ThrowIfNull(assembly);
|
||||
if (!ReferenceEquals(frame, assembly.Frame))
|
||||
throw new System.ArgumentException(
|
||||
"The look-in slots must be appended to the assembly's clip frame.",
|
||||
nameof(frame));
|
||||
|
||||
for (int frameIndex = 0; frameIndex < lookInFrames.Count; frameIndex++)
|
||||
{
|
||||
PortalVisibilityFrame lookIn = lookInFrames[frameIndex];
|
||||
foreach (uint cellId in lookIn.OrderedVisibleCells)
|
||||
{
|
||||
if (!lookIn.CellViews.TryGetValue(cellId, out CellView? view))
|
||||
continue;
|
||||
|
||||
List<ClipViewSlice> slices = assembly.SliceScratch;
|
||||
slices.Clear();
|
||||
foreach (ViewPolygon poly in view.Polygons)
|
||||
{
|
||||
ClipPlaneSet cps = ClipPlaneSet.From(poly);
|
||||
if (cps.IsNothingVisible)
|
||||
continue;
|
||||
|
||||
int slot;
|
||||
Vector4[] planes;
|
||||
if (cps.Count > 0)
|
||||
{
|
||||
planes = cps.PlaneArray;
|
||||
slot = frame.AppendSlot(planes);
|
||||
}
|
||||
else
|
||||
{
|
||||
planes = System.Array.Empty<Vector4>();
|
||||
slot = 0;
|
||||
assembly.ScissorFallbacks++;
|
||||
}
|
||||
|
||||
slices.Add(new ClipViewSlice(slot, AabbOf(poly), planes));
|
||||
}
|
||||
|
||||
if (slices.Count == 0)
|
||||
continue;
|
||||
|
||||
ClipViewSlice[] packed = assembly.CopySlices(slices);
|
||||
var key = new LookInClipCell(frameIndex, cellId);
|
||||
assembly.LookInCellToViewSlices.Add(key, packed);
|
||||
assembly.LookInCellToSlot.Add(key, packed[0].Slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector4 AabbOf(ViewPolygon poly) =>
|
||||
new(poly.MinX, poly.MinY, poly.MaxX, poly.MaxY);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue