Character-select nameplate text (name / level / class) renders greyed-out instead of white — regression from FFP retirement (#544)
Summary
On the character selection screen, the info plate above each saved character (name, guild, class) used to render at full brightness (white name/guild, orange class). After the fixed-function-GL retirement (PR #544, commit 0702144c), the plate's text is dimmed/greyed-out. The frame box itself is fine; only the text is wrong. Reproducible on both the native Linux OpenGL build and the Wine build, because the cause is in platform-independent client rendering code.
This is the same regression wave as #549/#555 (BlendMesh fade), #556/#557 (tile resolution) — a rendering side effect of retiring fixed-function GL that wasn't caught. This specific one is still unfixed on current main.
Affected version
Where it renders
- Plate:
CCharInfoBalloon::Render() — src/source/Character/CharInfoBalloon.cpp (frame box via CSprite::Render(), then name/guild/class via g_pRenderText->RenderText(...)).
- Text path:
RenderText → UploadText → RenderBitmap(BITMAP_FONT, ...) at src/source/UI/Legacy/UIControls.cpp:2830.
- Glyph color is baked into the font atlas (white / orange), then modulated by the global
g_CurrentColor inside RenderBitmap (src/source/Render/Textures/ZzzOpenglUtil.cpp).
Root cause
PR #544 broke an implicit invariant that had kept the plate text white. Two changes combine:
-
src/source/Render/Sprites/Sprite.cpp — CSprite::Render() switched from real GL to the immediate renderer:
- ::glColor4ub(m_byRed, m_byGreen, m_byBlue, m_byAlpha); // old: 255,255,255,255 → set GL current color WHITE
+ IR::Color4ub(m_byRed, m_byGreen, m_byBlue, m_byAlpha); // new: feeds IR only, leaves g_CurrentColor untouched
The frame box used to set the GL current color to white immediately before the text draw, as a side effect.
-
src/source/Render/Textures/ZzzOpenglUtil.cpp — RenderBitmap() (default param Alpha = 0.f; the BITMAP_FONT call passes no alpha, so it takes the else branch):
float currColor[4] = { 1.f, 1.f, 1.f, 1.f };
if (Alpha > 0.f) { currColor[0]=currColor[1]=currColor[2]=1.f; currColor[3]=Alpha; }
else { memcpy(currColor, g_CurrentColor, sizeof(currColor)); } // reads the stale global color
CCharInfoBalloon::Render() never calls glColor itself, and BeginBitmap() does not reset the color. So the baked-white text atlas is now modulated by whatever value g_CurrentColor was left at by an earlier UI element (e.g. the dimmed-control greys, or a 1,1,1,0.3 dim-alpha draw). White atlas × grey modulator = greyed nameplate.
The balloon is uniquely hit because it was the one text site relying on the frame sprite's glColor to set white for it; ordinary UI text sites set their own glColor4f(1,1,1,1) first. Any other text site that inherited white purely from a preceding sprite has the same latent bug.
Suggested fix
Targeted (safe, restores exact pre-#544 behavior for this plate): in CCharInfoBalloon::Render(), right after CSprite::Render();:
CSprite::Render();
glColor4f(1.f, 1.f, 1.f, 1.f); // restore the white current-color the frame's glColor4ub used to set, for the baked text atlas
Systemic (broader, but a design call): force white right before the baked-atlas glyph draw in UIControls.cpp (at the EnableAlphaTest(); on line 2829, before RenderBitmap(BITMAP_FONT, ...)):
EnableAlphaTest();
glColor4f(1.f, 1.f, 1.f, 1.f);
RenderBitmap(BITMAP_FONT, ...);
This fixes every text site that inherited white from a preceding sprite, but would override any text intentionally dimmed via a preceding glColor (text alpha would then have to be passed explicitly). The maintainer knows best whether any site relies on that; if not, the systemic fix is the cleaner root-cause fix.
Character-select nameplate text (name / level / class) renders greyed-out instead of white — regression from FFP retirement (#544)
Summary
On the character selection screen, the info plate above each saved character (name, guild, class) used to render at full brightness (white name/guild, orange class). After the fixed-function-GL retirement (PR #544, commit
0702144c), the plate's text is dimmed/greyed-out. The frame box itself is fine; only the text is wrong. Reproducible on both the native Linux OpenGL build and the Wine build, because the cause is in platform-independent client rendering code.This is the same regression wave as #549/#555 (BlendMesh fade), #556/#557 (tile resolution) — a rendering side effect of retiring fixed-function GL that wasn't caught. This specific one is still unfixed on current
main.Affected version
mainat the time of writing (verified on the merge of perf(render): GLP series — Core Profile FPS regression investigation and fixes #560). Introduced by PR feat(render): GPU bone skinning (15-20x CPU win), retire fixed-function GL #544 ("feat(render): GPU bone skinning, retire fixed-function GL"), commit0702144c. No later commit touchesCharInfoBalloon.cppor restores white before the font draw.Where it renders
CCharInfoBalloon::Render()—src/source/Character/CharInfoBalloon.cpp(frame box viaCSprite::Render(), then name/guild/class viag_pRenderText->RenderText(...)).RenderText → UploadText → RenderBitmap(BITMAP_FONT, ...)atsrc/source/UI/Legacy/UIControls.cpp:2830.g_CurrentColorinsideRenderBitmap(src/source/Render/Textures/ZzzOpenglUtil.cpp).Root cause
PR #544 broke an implicit invariant that had kept the plate text white. Two changes combine:
src/source/Render/Sprites/Sprite.cpp—CSprite::Render()switched from real GL to the immediate renderer:The frame box used to set the GL current color to white immediately before the text draw, as a side effect.
src/source/Render/Textures/ZzzOpenglUtil.cpp—RenderBitmap()(default paramAlpha = 0.f; theBITMAP_FONTcall passes no alpha, so it takes theelsebranch):CCharInfoBalloon::Render()never callsglColoritself, andBeginBitmap()does not reset the color. So the baked-white text atlas is now modulated by whatever valueg_CurrentColorwas left at by an earlier UI element (e.g. the dimmed-control greys, or a1,1,1,0.3dim-alpha draw). White atlas × grey modulator = greyed nameplate.The balloon is uniquely hit because it was the one text site relying on the frame sprite's
glColorto set white for it; ordinary UI text sites set their ownglColor4f(1,1,1,1)first. Any other text site that inherited white purely from a preceding sprite has the same latent bug.Suggested fix
Targeted (safe, restores exact pre-#544 behavior for this plate): in
CCharInfoBalloon::Render(), right afterCSprite::Render();:Systemic (broader, but a design call): force white right before the baked-atlas glyph draw in
UIControls.cpp(at theEnableAlphaTest();on line 2829, beforeRenderBitmap(BITMAP_FONT, ...)):This fixes every text site that inherited white from a preceding sprite, but would override any text intentionally dimmed via a preceding
glColor(text alpha would then have to be passed explicitly). The maintainer knows best whether any site relies on that; if not, the systemic fix is the cleaner root-cause fix.