phase(N.4) Tasks 22+23: WbDrawDispatcher + surface metadata side-table
WbDrawDispatcher draws all entities through WB's ObjectRenderData (VAO/VBO per GfxObj, per-batch IBO) using acdream's TextureCache for texture resolution. Two-pass rendering (opaque+ClipMap, then translucent) matching the existing InstancedMeshRenderer pattern. Per-entity single-instance drawing for N.4 simplicity — true instancing grouping deferred to N.6. Atlas-tier entities: mesh from WB, texture from TextureCache via batch SurfaceId. Per-instance-tier entities: AnimatedEntityState drives part overrides + hidden-parts, palette/surface overrides resolve through TextureCache's composite-key caches. Side-table population (Task 23 folded in): WbMeshAdapter now takes DatCollection and populates AcSurfaceMetadataTable on first IncrementRefCount per GfxObj. The side-table provides TranslucencyKind (critical for ClipMap alpha-test on vegetation) plus Luminosity, Diffuse, SurfOpacity, NeedsUvRepeat, DisableFog for sky-pass and lighting. GameWindow wiring: when WbFoundationFlag is enabled, WbDrawDispatcher draws everything and InstancedMeshRenderer is skipped. Flag-off path is unchanged. Matrix composition: restPose * animOverride * entityWorld, matching the spec. Three MatrixCompositionTests verify the contract. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5b4fd4b61d
commit
01cff4144f
5 changed files with 507 additions and 8 deletions
|
|
@ -31,6 +31,8 @@ public sealed class GameWindow : IDisposable
|
|||
/// <summary>Phase N.4: WB-backed rendering pipeline adapter. Non-null only
|
||||
/// when <c>ACDREAM_USE_WB_FOUNDATION=1</c> is set; null otherwise.</summary>
|
||||
private AcDream.App.Rendering.Wb.WbMeshAdapter? _wbMeshAdapter;
|
||||
private AcDream.App.Rendering.Wb.EntitySpawnAdapter? _wbEntitySpawnAdapter;
|
||||
private AcDream.App.Rendering.Wb.WbDrawDispatcher? _wbDrawDispatcher;
|
||||
private SamplerCache? _samplerCache;
|
||||
private DebugLineRenderer? _debugLines;
|
||||
// K-fix4 (2026-04-26): default OFF. The orange BSP / green cylinder
|
||||
|
|
@ -1434,7 +1436,7 @@ public sealed class GameWindow : IDisposable
|
|||
if (AcDream.App.Rendering.Wb.WbFoundationFlag.IsEnabled)
|
||||
{
|
||||
var wbLogger = Microsoft.Extensions.Logging.Abstractions.NullLogger<AcDream.App.Rendering.Wb.WbMeshAdapter>.Instance;
|
||||
_wbMeshAdapter = new AcDream.App.Rendering.Wb.WbMeshAdapter(_gl, _datDir, wbLogger);
|
||||
_wbMeshAdapter = new AcDream.App.Rendering.Wb.WbMeshAdapter(_gl, _datDir, _dats, wbLogger);
|
||||
Console.WriteLine("[N.4] WbFoundation flag is ENABLED — routing static content through ObjectMeshManager.");
|
||||
}
|
||||
|
||||
|
|
@ -1486,12 +1488,20 @@ public sealed class GameWindow : IDisposable
|
|||
}
|
||||
wbEntitySpawnAdapter = new AcDream.App.Rendering.Wb.EntitySpawnAdapter(
|
||||
_textureCache, SequencerFactory);
|
||||
_wbEntitySpawnAdapter = wbEntitySpawnAdapter;
|
||||
}
|
||||
_worldState = new AcDream.App.Streaming.GpuWorldState(wbSpawnAdapter, wbEntitySpawnAdapter);
|
||||
}
|
||||
|
||||
_staticMesh = new InstancedMeshRenderer(_gl, _meshShader, _textureCache, _wbMeshAdapter);
|
||||
|
||||
if (AcDream.App.Rendering.Wb.WbFoundationFlag.IsEnabled
|
||||
&& _wbMeshAdapter is not null && _wbEntitySpawnAdapter is not null)
|
||||
{
|
||||
_wbDrawDispatcher = new AcDream.App.Rendering.Wb.WbDrawDispatcher(
|
||||
_gl, _meshShader, _textureCache, _wbMeshAdapter, _wbEntitySpawnAdapter);
|
||||
}
|
||||
|
||||
// Phase G.1 sky renderer — its own shader (sky.vert / sky.frag)
|
||||
// with depth writes off + far plane 1e6 so celestial meshes
|
||||
// never clip. Shares the TextureCache with the static pipeline.
|
||||
|
|
@ -6326,10 +6336,20 @@ public sealed class GameWindow : IDisposable
|
|||
animatedIds.Add(k);
|
||||
}
|
||||
|
||||
_staticMesh?.Draw(camera, _worldState.LandblockEntries, frustum,
|
||||
neverCullLandblockId: playerLb,
|
||||
visibleCellIds: visibility?.VisibleCellIds,
|
||||
animatedEntityIds: animatedIds);
|
||||
if (_wbDrawDispatcher is not null)
|
||||
{
|
||||
_wbDrawDispatcher.Draw(camera, _worldState.LandblockEntries, frustum,
|
||||
neverCullLandblockId: playerLb,
|
||||
visibleCellIds: visibility?.VisibleCellIds,
|
||||
animatedEntityIds: animatedIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticMesh?.Draw(camera, _worldState.LandblockEntries, frustum,
|
||||
neverCullLandblockId: playerLb,
|
||||
visibleCellIds: visibility?.VisibleCellIds,
|
||||
animatedEntityIds: animatedIds);
|
||||
}
|
||||
|
||||
// Phase G.1 / E.3: draw all live particles after opaque
|
||||
// scene geometry so alpha blending composites correctly.
|
||||
|
|
@ -8710,6 +8730,7 @@ public sealed class GameWindow : IDisposable
|
|||
_combatChatTranslator?.Dispose();
|
||||
_liveSession?.Dispose();
|
||||
_audioEngine?.Dispose(); // Phase E.2: stop all voices, close AL context
|
||||
_wbDrawDispatcher?.Dispose();
|
||||
_staticMesh?.Dispose();
|
||||
_skyRenderer?.Dispose(); // depends on sampler cache; dispose first
|
||||
_samplerCache?.Dispose();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue