fix(rendering): port retail shared alpha list
Queue translucent world GfxObj batches and scene particles in one stable far-to-near stream using transformed DAT sort centers, then drain it at retail's landscape and final-world boundaries. Preserve authored blend, cull, lighting, opacity, and adjacent-only batching so particles behind lifestones are composited through the crystal instead of overpainting it. Release build succeeds and all 5,914 tests pass with five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
ec1bb19609
commit
6b0472ee32
14 changed files with 1083 additions and 34 deletions
|
|
@ -413,7 +413,12 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
/// produces under the collector pattern.
|
||||
/// </summary>
|
||||
private static CachedBatch MakeCachedBatch(
|
||||
uint ibo, uint firstIndex, int indexCount, ulong texHandle, Matrix4x4? restPose = null)
|
||||
uint ibo,
|
||||
uint firstIndex,
|
||||
int indexCount,
|
||||
ulong texHandle,
|
||||
Matrix4x4? restPose = null,
|
||||
Vector3? localSortCenter = null)
|
||||
{
|
||||
var key = new GroupKey(
|
||||
Ibo: ibo,
|
||||
|
|
@ -423,7 +428,11 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
BindlessTextureHandle: texHandle,
|
||||
TextureLayer: 0,
|
||||
Translucency: TranslucencyKind.Opaque);
|
||||
return new CachedBatch(key, texHandle, restPose ?? Matrix4x4.Identity);
|
||||
return new CachedBatch(
|
||||
key,
|
||||
texHandle,
|
||||
restPose ?? Matrix4x4.Identity,
|
||||
localSortCenter ?? Vector3.Zero);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -479,7 +488,8 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
// Production code: this is the !isAnimated && _cache.TryGet branch
|
||||
// at the top of the per-entity loop body in Draw.
|
||||
var groups = new Dictionary<GroupKey, List<Matrix4x4>>();
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m)
|
||||
var sortCenters = new List<Vector3>();
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m, Vector3 localSortCenter)
|
||||
{
|
||||
if (!groups.TryGetValue(k, out var list))
|
||||
{
|
||||
|
|
@ -487,6 +497,7 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
groups[k] = list;
|
||||
}
|
||||
list.Add(m);
|
||||
sortCenters.Add(localSortCenter);
|
||||
}
|
||||
|
||||
Assert.True(cache.TryGet(EntityId, LandblockId, out var entryHit));
|
||||
|
|
@ -508,6 +519,35 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
// appended matrix must equal entityWorld.
|
||||
foreach (var (_, list) in groups)
|
||||
Assert.Equal(entityWorld, list[0]);
|
||||
Assert.All(sortCenters, center => Assert.Equal(Vector3.Zero, center));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyCacheHit_PreservesAuthoredSortCenter()
|
||||
{
|
||||
Vector3 authoredCenter = new(1.25f, -2.5f, 7.75f);
|
||||
var entry = new EntityCacheEntry
|
||||
{
|
||||
EntityId = 100,
|
||||
LandblockHint = 0xA9B40000u,
|
||||
Batches =
|
||||
[
|
||||
MakeCachedBatch(
|
||||
ibo: 1,
|
||||
firstIndex: 0,
|
||||
indexCount: 6,
|
||||
texHandle: 0xAA,
|
||||
localSortCenter: authoredCenter),
|
||||
],
|
||||
};
|
||||
Vector3 observedCenter = default;
|
||||
|
||||
WbDrawDispatcher.ApplyCacheHit(
|
||||
entry,
|
||||
Matrix4x4.Identity,
|
||||
(_, _, center) => observedCenter = center);
|
||||
|
||||
Assert.Equal(authoredCenter, observedCenter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -748,7 +788,7 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
const uint EntityId = 100;
|
||||
const int MeshRefCount = 3;
|
||||
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m)
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m, Vector3 localSortCenter)
|
||||
{
|
||||
if (!groups.TryGetValue(k, out var list))
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue