@
fix(D.2b): point-sample the dat-font atlas so UI text is pixel-crisp The font glyph atlas was uploaded with bilinear (Linear) min/mag filtering, which softens the small dat-font glyphs (the menu/button text "blur"). Add a nearest-filter path to UploadRgba8/GetOrUploadRenderSurface and use it for the font atlases only (world + other UI surfaces keep bilinear). Combined with the existing per-glyph pixel-snap, glyph texels now map 1:1 to screen pixels. Sharpens all dat-font text (transcript, menu, Send/Chat buttons, vitals numbers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
parent
621a4ab468
commit
828bec5fb5
2 changed files with 12 additions and 7 deletions
|
|
@ -119,7 +119,7 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
||||||
/// Magenta — wire a UI palette when one is actually encountered). Returns a
|
/// Magenta — wire a UI palette when one is actually encountered). Returns a
|
||||||
/// 1x1 magenta handle on miss.
|
/// 1x1 magenta handle on miss.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint GetOrUploadRenderSurface(uint renderSurfaceId, out int width, out int height)
|
public uint GetOrUploadRenderSurface(uint renderSurfaceId, out int width, out int height, bool nearest = false)
|
||||||
{
|
{
|
||||||
if (_handlesByRenderSurfaceId.TryGetValue(renderSurfaceId, out var existing)
|
if (_handlesByRenderSurfaceId.TryGetValue(renderSurfaceId, out var existing)
|
||||||
&& _rsSizeById.TryGetValue(renderSurfaceId, out var sz))
|
&& _rsSizeById.TryGetValue(renderSurfaceId, out var sz))
|
||||||
|
|
@ -139,7 +139,7 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
||||||
decoded = DecodedTexture.Magenta;
|
decoded = DecodedTexture.Magenta;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint h = UploadRgba8(decoded);
|
uint h = UploadRgba8(decoded, nearest);
|
||||||
_handlesByRenderSurfaceId[renderSurfaceId] = h;
|
_handlesByRenderSurfaceId[renderSurfaceId] = h;
|
||||||
_rsSizeById[renderSurfaceId] = (decoded.Width, decoded.Height);
|
_rsSizeById[renderSurfaceId] = (decoded.Width, decoded.Height);
|
||||||
width = decoded.Width; height = decoded.Height;
|
width = decoded.Width; height = decoded.Height;
|
||||||
|
|
@ -542,7 +542,7 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
||||||
return composed;
|
return composed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint UploadRgba8(DecodedTexture decoded)
|
private uint UploadRgba8(DecodedTexture decoded, bool nearest = false)
|
||||||
{
|
{
|
||||||
uint tex = _gl.GenTexture();
|
uint tex = _gl.GenTexture();
|
||||||
_gl.BindTexture(TextureTarget.Texture2D, tex);
|
_gl.BindTexture(TextureTarget.Texture2D, tex);
|
||||||
|
|
@ -559,8 +559,11 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
||||||
PixelType.UnsignedByte,
|
PixelType.UnsignedByte,
|
||||||
p);
|
p);
|
||||||
|
|
||||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
// Point (nearest) sampling for pixel-exact UI text — bilinear softens the dat
|
||||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
// font's small glyphs. Other surfaces use bilinear.
|
||||||
|
int filter = nearest ? (int)TextureMinFilter.Nearest : (int)TextureMinFilter.Linear;
|
||||||
|
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, filter);
|
||||||
|
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, filter);
|
||||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
|
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
|
||||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
|
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,11 +101,13 @@ public sealed class UiDatFont
|
||||||
if (font.ForegroundSurfaceDataId == 0)
|
if (font.ForegroundSurfaceDataId == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
uint fgTex = cache.GetOrUploadRenderSurface(font.ForegroundSurfaceDataId, out int fgW, out int fgH);
|
// Point-sample the glyph atlases (nearest) so small UI text stays pixel-crisp;
|
||||||
|
// bilinear softens the dat font noticeably (the chat menu/button text "blur").
|
||||||
|
uint fgTex = cache.GetOrUploadRenderSurface(font.ForegroundSurfaceDataId, out int fgW, out int fgH, nearest: true);
|
||||||
|
|
||||||
uint bgTex = 0; int bgW = 0, bgH = 0;
|
uint bgTex = 0; int bgW = 0, bgH = 0;
|
||||||
if (font.BackgroundSurfaceDataId != 0)
|
if (font.BackgroundSurfaceDataId != 0)
|
||||||
bgTex = cache.GetOrUploadRenderSurface(font.BackgroundSurfaceDataId, out bgW, out bgH);
|
bgTex = cache.GetOrUploadRenderSurface(font.BackgroundSurfaceDataId, out bgW, out bgH, nearest: true);
|
||||||
|
|
||||||
// Build the char->descriptor lookup. FontCharDesc.Unicode is the code
|
// Build the char->descriptor lookup. FontCharDesc.Unicode is the code
|
||||||
// point; for Latin-1 fonts this is a direct char cast. Last write wins
|
// point; for Latin-1 fonts this is a direct char cast. Last write wins
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue