feat(D.2b): Step-0 chrome sprites confirmed + direct-RenderSurface upload path
Step-0 prove-out result: retail UI chrome sprites are RenderSurface objects (0x06xxxxxx) that must be decoded DIRECTLY, not via the Surface->SurfaceTexture chain GetOrUpload uses for world materials (which produced 1x1 magenta/garbage). Added TextureCache.GetOrUploadRenderSurface(id, out w, out h) — Portal/HighRes TryGet<RenderSurface> -> DecodeRenderSurface(palette:null) -> upload, separately cached. This is the path UI chrome + (later) dat fonts use. Confirmed the universal floating-window bevel is an 8-piece border + center fill: center 0x06004CC2 (48x48) edges 0x060074BF/C1 (10x5 horiz) 0x060074C0/C2 (5x10 vert) corners 0x060074C3..C6 (5x5) Recorded in RetailChromeSprites.cs (edge/corner->position mapping is a best guess pending the LayoutDesc 0x21000040 parse; visually confirmed at panel render). The memory-note ids were right; only the decode path was wrong. Temporary prove-out harness (added to GameWindow.OnRender) removed. proveout*.log gitignored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
66888d2c8e
commit
8e91805206
3 changed files with 92 additions and 0 deletions
|
|
@ -31,6 +31,12 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
private readonly Dictionary<(uint surfaceId, uint origTexOverride, ulong paletteHash), uint> _handlesByPalette = new();
|
||||
private uint _magentaHandle;
|
||||
|
||||
// Direct-RenderSurface caches for UI sprites: 0x06xxxxxx RenderSurface ids
|
||||
// decoded directly (Portal/HighRes → DecodeRenderSurface), bypassing the
|
||||
// Surface→SurfaceTexture chain that GetOrUpload uses for world materials.
|
||||
private readonly Dictionary<uint, uint> _handlesByRenderSurfaceId = new();
|
||||
private readonly Dictionary<uint, (int w, int h)> _rsSizeById = new();
|
||||
|
||||
private readonly Wb.BindlessSupport? _bindless;
|
||||
|
||||
// Bindless / Texture2DArray parallel caches. Keys mirror the legacy three
|
||||
|
|
@ -103,6 +109,43 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
return h;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload a UI sprite by its RenderSurface DataId (0x06xxxxxx), decoded
|
||||
/// DIRECTLY (Portal/HighRes → DecodeRenderSurface) rather than through the
|
||||
/// Surface→SurfaceTexture chain that <see cref="GetOrUpload(uint)"/> uses
|
||||
/// for world-geometry materials. This is the correct path for retail UI
|
||||
/// chrome + font glyph sheets, which reference RenderSurface directly.
|
||||
/// Palette is null for now (a paletted INDEX16/P8 UI sprite would return
|
||||
/// Magenta — wire a UI palette when one is actually encountered). Returns a
|
||||
/// 1x1 magenta handle on miss.
|
||||
/// </summary>
|
||||
public uint GetOrUploadRenderSurface(uint renderSurfaceId, out int width, out int height)
|
||||
{
|
||||
if (_handlesByRenderSurfaceId.TryGetValue(renderSurfaceId, out var existing)
|
||||
&& _rsSizeById.TryGetValue(renderSurfaceId, out var sz))
|
||||
{
|
||||
width = sz.w; height = sz.h;
|
||||
return existing;
|
||||
}
|
||||
|
||||
DecodedTexture decoded;
|
||||
if (_dats.Portal.TryGet<RenderSurface>(renderSurfaceId, out var rs)
|
||||
|| _dats.HighRes.TryGet<RenderSurface>(renderSurfaceId, out rs))
|
||||
{
|
||||
decoded = SurfaceDecoder.DecodeRenderSurface(rs, palette: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded = DecodedTexture.Magenta;
|
||||
}
|
||||
|
||||
uint h = UploadRgba8(decoded);
|
||||
_handlesByRenderSurfaceId[renderSurfaceId] = h;
|
||||
_rsSizeById[renderSurfaceId] = (decoded.Width, decoded.Height);
|
||||
width = decoded.Width; height = decoded.Height;
|
||||
return h;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alpha-channel histogram for one decoded texture. Used to diagnose
|
||||
/// "why are clouds not transparent" — if cloud textures come out with
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue