refactor(render): cull terrain by walk in-view cells
This commit is contained in:
parent
98d2d43fdc
commit
837a33baff
3 changed files with 54 additions and 14 deletions
|
|
@ -68,6 +68,7 @@ public sealed partial class TerrainModernRenderer : IDisposable
|
|||
// Reusable per-frame buffers.
|
||||
private readonly List<int> _visibleSlots = new();
|
||||
private readonly HashSet<uint> _visibleCellIds = new();
|
||||
private readonly HashSet<uint> _walkVisibleLandblocks = new();
|
||||
private DrawElementsIndirectCommand[] _deicScratch = Array.Empty<DrawElementsIndirectCommand>();
|
||||
|
||||
// Diag.
|
||||
|
|
@ -204,34 +205,58 @@ public sealed partial class TerrainModernRenderer : IDisposable
|
|||
FrustumPlanes? frustum = null,
|
||||
uint? neverCullLandblockId = null,
|
||||
ReadOnlySpan<Vector4> clipPlanes = default,
|
||||
Vector4? ndcClipAabb = null)
|
||||
Vector4? ndcClipAabb = null,
|
||||
IReadOnlySet<uint>? inViewLandcells = null)
|
||||
{
|
||||
if (_alloc.LoadedCount == 0) return;
|
||||
|
||||
Matrix4x4 viewProjection = camera.View * camera.Projection;
|
||||
|
||||
// Campaign FW4: RetailFrameWalk is the sole visibility authority.
|
||||
// Terrain remains one full-landblock MDI draw, but only landblocks
|
||||
// containing a walk-admitted landcell participate, and the published
|
||||
// landcell set is the walk's exact in_view set rather than a second
|
||||
// frustum-derived approximation.
|
||||
_walkVisibleLandblocks.Clear();
|
||||
if (inViewLandcells is not null)
|
||||
{
|
||||
foreach (uint cellId in inViewLandcells)
|
||||
{
|
||||
_walkVisibleLandblocks.Add(cellId & 0xFFFF0000u);
|
||||
_visibleCellIds.Add(cellId);
|
||||
}
|
||||
}
|
||||
|
||||
// Build visible slot list with per-slot frustum cull.
|
||||
_visibleSlots.Clear();
|
||||
for (int slot = 0; slot < _slots.Length; slot++)
|
||||
{
|
||||
var data = _slots[slot];
|
||||
if (data is null) continue;
|
||||
if (inViewLandcells is not null
|
||||
&& !_walkVisibleLandblocks.Contains(data.LandblockId & 0xFFFF0000u))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (frustum is not null && data.LandblockId != neverCullLandblockId)
|
||||
{
|
||||
if (!FrustumCuller.IsAabbVisible(frustum.Value, data.AabbMin, data.AabbMax))
|
||||
continue;
|
||||
}
|
||||
_visibleSlots.Add(slot);
|
||||
CollectVisibleCells(
|
||||
_visibleCellIds,
|
||||
data.LandblockId,
|
||||
data.WorldOrigin,
|
||||
data.AabbMin.Z,
|
||||
data.AabbMax.Z,
|
||||
frustum,
|
||||
viewProjection,
|
||||
clipPlanes,
|
||||
ndcClipAabb);
|
||||
if (inViewLandcells is null)
|
||||
{
|
||||
CollectVisibleCells(
|
||||
_visibleCellIds,
|
||||
data.LandblockId,
|
||||
data.WorldOrigin,
|
||||
data.AabbMin.Z,
|
||||
data.AabbMax.Z,
|
||||
frustum,
|
||||
viewProjection,
|
||||
clipPlanes,
|
||||
ndcClipAabb);
|
||||
}
|
||||
}
|
||||
if (_visibleSlots.Count == 0) return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue