How to Troubleshoot Missing Text Squares When Integrating Dear ImGui
TLDR: Missing text squares in Dear ImGui indicate that the ImFontAtlas texture is not uploaded to the GPU or the current font lacks the requested glyphs; verify that io.Fonts->TexID is non-null after initialization and that your backend's CreateDeviceObjects function successfully uploads the font texture.
When integrating the ocornut/imgui library into your graphics application, encountering squares instead of text is a common symptom of font system misconfiguration. This troubleshooting guide explains how to diagnose and resolve missing text squares when integrating ImGui by examining the font atlas architecture, glyph fallback mechanisms, and backend texture upload requirements implemented in the source code.
How Dear ImGui Renders Text and Handles Missing Glyphs
Dear ImGui renders text by looking up glyphs in an ImFontAtlas. When ImFont::FindGlyph() cannot locate a specific character, the renderer falls back to a placeholder square. This fallback mechanism is implemented in imgui_draw.cpp around line 5345, where the draw routine substitutes a generic "missing glyph" box when glyph lookup fails.
The ImFontAtlas holds all rasterized glyphs and the font texture. According to the source in imgui.cpp (lines 3180-3190), ImGui automatically creates a default font if none is explicitly added, choosing between AddFontDefaultVector() and AddFontDefaultBitmap() based on DPI and style size settings.
Common Causes of Missing Text Squares
Null Font Texture (TexID)
If the GPU texture containing the font atlas is never uploaded, io.Fonts->TexID remains null. This occurs when the backend's device object creation is skipped or fails. In this scenario, all text rendering will display squares because the draw calls reference an empty or invalid texture.
Missing Glyph Ranges
When only specific characters appear as squares while others render correctly, the default font lacks those glyphs. The default embedded font covers basic ASCII but excludes Unicode symbols, emojis, or non-Latin scripts, causing FindGlyph() to return the missing glyph fallback.
High-DPI Scaling Mismatches
On high-DPI monitors, ImGui may automatically select the bitmap font via AddFontDefaultBitmap() instead of the scalable vector version. The bitmap resolution may be insufficient for the display scale, or the automatic selection logic may fail to provide the necessary glyph coverage.
Backend Context Recreation
Switching graphics backends or recreating the device context (e.g., after a Vulkan swapchain rebuild or OpenGL context loss) without re-uploading the font texture leaves TexID pointing to invalid GPU memory. The backend must recreate the texture through its CreateDeviceObjects routine.
Step-by-Step Troubleshooting Checklist
Follow this verification sequence to identify the root cause:
-
Create the context: Call
ImGui::CreateContext()before any other ImGui function. -
Load a font explicitly: Force the vector font for DPI-aware applications or load a custom TTF with required glyph ranges.
-
Build the atlas: While backends typically handle this implicitly, ensure
io.Fonts->Build()completes successfully. -
Upload the texture: Verify your backend's device object creation runs (e.g.,
ImGui_ImplOpenGL3_CreateDeviceObjects()inimgui_impl_opengl3.cpp). -
Verify TexID: After
ImGui::NewFrame(), assert thatio.Fonts->TexID != nullptrto confirm successful GPU upload.
Code Solutions for Missing Text Squares
Forcing the Vector Font for High-DPI Displays
Explicitly select the scalable vector font to avoid automatic bitmap selection on high-DPI systems:
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// Force scalable vector font instead of bitmap
io.Fonts->AddFontDefaultVector();
// Backend initialization uploads the texture
ImGui_ImplOpenGL3_Init("#version 130");
ImGui_ImplOpenGL3_CreateDeviceObjects(); // Critical: uploads TexID to GPU
Loading Custom Fonts with Unicode Support
Load system or custom TTF files that contain the specific glyph ranges you need:
ImGuiIO& io = ImGui::GetIO();
ImFontConfig cfg;
cfg.MergeMode = true; // Merge with existing fonts
// Load font with extended Unicode ranges
io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/seguiemj.ttf", 16.0f,
&cfg, io.Fonts->GetGlyphRangesDefault());
Runtime Verification of Font Texture
Insert this assertion after NewFrame() to catch missing texture uploads immediately:
ImGui::NewFrame();
IM_ASSERT(ImGui::GetIO().Fonts->TexID != nullptr &&
"Font texture not uploaded - check backend CreateDeviceObjects!");
Summary
- Missing text squares indicate glyph lookup failure or missing font texture upload in ocornut/imgui.
- Verify
io.Fonts->TexIDis non-null after initialization to confirm the backend successfully uploaded the texture viaCreateDeviceObjects. - Use
AddFontDefaultVector()instead of relying on automatic bitmap selection for high-DPI displays. - Load custom TTF files via
AddFontFromFileTTF()when displaying Unicode symbols or non-ASCII characters not covered by the default font. - Always recreate device objects (e.g.,
ImGui_ImplOpenGL3_CreateDeviceObjects()) after graphics context loss or backend switches.
Frequently Asked Questions
Why do I see squares instead of text in ImGui?
Squares appear when ImFont::FindGlyph() cannot locate a glyph in the ImFontAtlas, triggering the fallback rendering defined in imgui_draw.cpp. This occurs either because the specific character is missing from the loaded font ranges, or because the entire font texture failed to upload to the GPU and TexID remains null.
How do I fix missing squares after switching graphics backends?
When transitioning between OpenGL, Vulkan, or DirectX backends, you must call the backend's *_DestroyDeviceObjects() followed by *_CreateDeviceObjects() to rebuild and re-upload the font texture. If TexID becomes invalid during the transition, all text will render as squares until the texture is re-uploaded to the new device context.
Can I use system fonts to fix missing text squares?
Yes, use io.Fonts->AddFontFromFileTTF() to load system fonts like Segoe UI or Arial that contain the missing glyph ranges. Ensure you call this before the backend uploads the texture (typically before ImGui_ImplOpenGL3_CreateDeviceObjects()), and verify the file path is accessible to your application at runtime.
What is the difference between AddFontDefaultVector and AddFontDefaultBitmap?
AddFontDefaultVector() loads the embedded ProggyClean font as scalable vector data, suitable for high-DPI displays at any size, while AddFontDefaultBitmap() uses a pre-rasterized bitmap optimized for 13px rendering. The automatic selection logic in imgui.cpp (around line 3180) chooses between them based on DPI settings, but explicitly calling AddFontDefaultVector() ensures crisp text rendering regardless of display scale.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →