native_render: HiDPI glyph pages, sharp UI upscaling, 4x MSAA
- CGraphicFontTexture rasterises glyph pages at the swapchain density (UISetFontOversample, MT_FONT_OVERSAMPLE) with anti-aliased coverage; metrics, packing and UVs stay the 40250 1x values. Default 1 keeps the verbatim bilevel path (Godot unchanged). - native.frag: sharp-bilinear sampling for magnified UI textures. - Multisampled colour/depth with a resolve into the swapchain (MT_MSAA, default 4); stats line reports msaa=N. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
22ca5da387
commit
52ccb80d01
@@ -5,6 +5,38 @@
|
||||
#include "EterBase/Stl.h"
|
||||
|
||||
#include "EterLib/Util.h"
|
||||
#include "UIRenderCommands.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
// PORT: HiDPI glyph pages (UISetFontOversample). With a scale s > 1 the page DIB and texture are
|
||||
// s times larger and each glyph is drawn with an s-times font into the s-scaled cell, while the
|
||||
// 40250 metrics (width, height, advance), the packing and therefore the page UVs stay the logical
|
||||
// 1x values: text layout is unchanged, only the texels get finer.
|
||||
namespace {
|
||||
int g_font_oversample = 1;
|
||||
bool g_font_oversample_latched = false;
|
||||
// The 1x HFONT a CGraphicFontTexture measures with -> its s-times twin that draws.
|
||||
std::unordered_map<HFONT, HFONT> g_oversampled_fonts;
|
||||
|
||||
int FontOversample()
|
||||
{
|
||||
g_font_oversample_latched = true;
|
||||
return g_font_oversample;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void UISetFontOversample(int scale)
|
||||
{
|
||||
if (g_font_oversample_latched)
|
||||
return;
|
||||
g_font_oversample = scale < 1 ? 1 : (scale > 4 ? 4 : scale);
|
||||
}
|
||||
|
||||
int UIFontOversample()
|
||||
{
|
||||
return g_font_oversample;
|
||||
}
|
||||
|
||||
CGraphicFontTexture::CGraphicFontTexture()
|
||||
{
|
||||
@@ -49,6 +81,13 @@ void CGraphicFontTexture::Destroy()
|
||||
|
||||
while(i != m_fontMap.end())
|
||||
{
|
||||
TFontMap::mapped_type hFont = i->second;
|
||||
auto hi = g_oversampled_fonts.find(hFont);
|
||||
if (hi != g_oversampled_fonts.end())
|
||||
{
|
||||
DeleteObject((HGDIOBJ)hi->second);
|
||||
g_oversampled_fonts.erase(hi);
|
||||
}
|
||||
DeleteObject((HGDIOBJ)i->second);
|
||||
++i;
|
||||
}
|
||||
@@ -86,7 +125,8 @@ bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bI
|
||||
if (GetMaxTextureHeight() > 512)
|
||||
height = 512;
|
||||
|
||||
if (!m_dib.Create(ms_hDC, width, height))
|
||||
const int s = FontOversample();
|
||||
if (!m_dib.Create(ms_hDC, width * s, height * s))
|
||||
return false;
|
||||
|
||||
HDC hDC = m_dib.GetDCHandle();
|
||||
@@ -139,6 +179,13 @@ HFONT CGraphicFontTexture::GetFont(WORD codePage)
|
||||
hFont = CreateFontIndirect(&logFont);
|
||||
|
||||
m_fontMap.insert(TFontMap::value_type(codePage, hFont));
|
||||
|
||||
if (const int s = FontOversample(); s > 1 && hFont)
|
||||
{
|
||||
logFont.lfHeight = m_fontSize * s;
|
||||
if (HFONT hHiFont = CreateFontIndirect(&logFont))
|
||||
g_oversampled_fonts[hFont] = hHiFont;
|
||||
}
|
||||
}
|
||||
|
||||
return hFont;
|
||||
@@ -210,7 +257,8 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::GetCharacterInfo
|
||||
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterInfomation(TCharacterKey code)
|
||||
{
|
||||
HDC hDC = m_dib.GetDCHandle();
|
||||
SelectObject(hDC, GetFont(code.first));
|
||||
HFONT hFont = GetFont(code.first);
|
||||
SelectObject(hDC, hFont);
|
||||
|
||||
wchar_t keyValue = code.second;
|
||||
|
||||
@@ -232,8 +280,9 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
||||
|
||||
LONG lAdvance = ceilf( stABC.abcfA + stABC.abcfB + stABC.abcfC );
|
||||
|
||||
int width = m_dib.GetWidth();
|
||||
int height = m_dib.GetHeight();
|
||||
const int s = FontOversample();
|
||||
int width = m_dib.GetWidth() / s;
|
||||
int height = m_dib.GetHeight() / s;
|
||||
|
||||
if (m_x + size.cx >= (width - 1))
|
||||
{
|
||||
@@ -255,6 +304,26 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
||||
}
|
||||
}
|
||||
|
||||
auto hi = s > 1 ? g_oversampled_fonts.find(hFont) : g_oversampled_fonts.end();
|
||||
if (hi != g_oversampled_fonts.end())
|
||||
{
|
||||
// Draw with the s-times font into the s-scaled cell and keep its anti-aliasing as
|
||||
// A4R4G4B4 white with coverage alpha (1x keeps 40250's bilevel threshold below).
|
||||
SelectObject(hDC, hi->second);
|
||||
TextOutW(hDC, m_x * s, m_y * s, &keyValue, 1);
|
||||
SelectObject(hDC, hFont);
|
||||
|
||||
const int nDIBWidth = m_dib.GetWidth();
|
||||
DWORD* pdwRow = (DWORD*)m_dib.GetPointer() + nDIBWidth * (m_y * s) + m_x * s;
|
||||
for (int y = 0; y < size.cy * s; ++y, pdwRow += nDIBWidth)
|
||||
for (int x = 0; x < size.cx * s; ++x)
|
||||
{
|
||||
const DWORD alpha = ((pdwRow[x] & 0xff) * 15 + 127) / 255;
|
||||
pdwRow[x] = alpha ? ((alpha << 12) | 0x0fff) : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextOutW(hDC, m_x, m_y, &keyValue, 1);
|
||||
|
||||
int nChrX;
|
||||
@@ -276,6 +345,7 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
||||
pdwDIBRow[nChrX]=(pdwDIBRow[nChrX]&0xff) ? 0xffff : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float rhwidth = 1.0f / float(width);
|
||||
float rhheight = 1.0f / float(height);
|
||||
|
||||
@@ -72,3 +72,10 @@ void UIRenderAdd(UIRenderCommand command);
|
||||
const std::vector<UIRenderCommand>& UIRenderCommands();
|
||||
void UIRenderSetClip(float x, float y, float width, float height);
|
||||
void UIRenderRestoreClip();
|
||||
|
||||
// HiDPI text: CGraphicFontTexture rasterises its glyph pages at this multiple of the logical font
|
||||
// size (the swapchain's pixels per UI pixel) while keeping the 40250 glyph metrics and page UVs in
|
||||
// logical pixels. 1 (the default) is the verbatim 40250 path. Latched when the first font page is
|
||||
// created, so set it before the game creates fonts.
|
||||
void UISetFontOversample(int scale);
|
||||
int UIFontOversample();
|
||||
|
||||
Reference in New Issue
Block a user