How to Handle DPI Scaling and High‑DPI Displays in Dear ImGui

Enable DPI awareness in your platform backend, set io.ConfigDpiScaleFonts and io.ConfigDpiScaleViewports to true (Docking branch), and rely on ImGuiIO::DisplayFramebufferScale or per‑viewport Scale values to render crisp UI on Retina and high‑resolution monitors.

Dear ImGui (ocornut/imgui) provides built‑in support for high‑DPI (HiDPI) displays through a combination of IO configuration flags, per‑viewport scaling data, and backend‑specific helpers. Proper DPI scaling ensures that your interface remains sharp and readable on modern 4K monitors, macOS Retina displays, and mixed‑DPI multi‑monitor setups.

Understanding ImGui's DPI Architecture

Dear ImGui stores display density information in two primary locations: the global ImGuiIO structure and individual ImGuiViewport objects. Understanding how these interact is essential for implementing correct scaling across different monitors.

DisplayFramebufferScale and Viewport Scaling

The DisplayFramebufferScale field in ImGuiIO represents the ratio between logical pixels and physical framebuffer pixels for the main display. According to the source in imgui.h at line 2420, this value feeds directly into each viewport's FramebufferScale.

Each ImGuiViewport maintains its own Scale value (defined at line 3486 in imgui.h). This per‑viewport scale derives from the platform window's DPI and is updated by the backend during NewFrame(). When multi‑viewport support is enabled via ImGuiConfigFlags_ViewportsEnable, each window can carry a distinct DPI factor, allowing the UI to adapt as you drag windows between monitors with different densities.

Automatic Font Scaling vs. Manual Style Scaling

The Docking branch introduces two critical flags for automatic DPI handling:

  • ConfigDpiScaleFonts: When enabled, Dear ImGui automatically rebuilds the font atlas with adjusted pixel sizes whenever the DPI changes. This eliminates the need for manual font scaling calculations.
  • ConfigDpiScaleViewports: When enabled, the entire UI scales automatically based on the monitor DPI.

If you do not enable ConfigDpiScaleFonts, you must manually multiply style metrics by the DPI factor. As implemented in imgui.cpp at line 9194, fields within the ImGuiStyle struct (such as CellPadding and FrameRounding) require manual adjustment to maintain consistent proportions.

Platform‑Specific DPI Awareness Setup

Before Dear ImGui can handle DPI scaling, the underlying platform window and process must declare DPI awareness. The official backends provide helpers that wrap platform‑specific APIs.

Windows (Win32)

For Windows applications, call ImGui_ImplWin32_EnableDpiAwareness() before creating your window. This helper (located at lines 24‑30 in backends/imgui_impl_win32.cpp) invokes SetProcessDpiAwarenessContext to enable per‑monitor DPI awareness without requiring a manifest file.

// Call before creating the main window
ImGui_ImplWin32_EnableDpiAwareness();

// Create your window normally
HWND hwnd = CreateWindowExW(...);

Alternatively, if using SDL2 or GLFW on Windows, you can call the Windows‑specific SetProcessDPIAware() after window creation.

SDL2

Pass the SDL_WINDOW_ALLOW_HIGHDPI flag when creating your window. This tells SDL to create a high‑DPI compatible framebuffer on macOS and some Windows configurations.

SDL_Window* window = SDL_CreateWindow(
    "Demo", 
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
    1280, 720,
    SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI
);

// Windows-specific additional step
::SetProcessDPIAware();

GLFW

Enable high‑DPI support using window hints before creating the GLFW window. The backend will automatically query monitor content scale using glfwGetMonitorContentScale.

glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Demo", NULL, NULL);

Configuring ImGui for High‑DPI

After initializing your platform backend, configure the ImGui IO structure to enable automatic scaling. These settings must be applied before your first call to ImGui::NewFrame().

ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();

// Required for per-monitor DPI scaling
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

// Docking branch only: enable automatic scaling
io.ConfigDpiScaleFonts = true;
io.ConfigDpiScaleViewports = true;

The CurrentDpiScale value (handled internally at line 4688 in imgui.cpp) tracks the runtime DPI scale used by the renderer for fringe sizes and line thickness. This value propagates to ImDrawData::FramebufferScale, ensuring that all built‑in widgets appear sharp regardless of display density.

Handling Custom Rendering and Geometry

When implementing custom draw calls or integrating external rendering, you must manually apply the DPI scale to coordinates and sizes. Retrieve the scale from the current viewport and multiply your geometry accordingly.

ImGui::NewFrame();

// Display current scale for debugging
ImGui::Text("Current DPI scale: %.2f", ImGui::GetIO().DisplayFramebufferScale.x);

// Get the scale for the current window's viewport
ImGuiViewport* vp = ImGui::GetWindowViewport();
float scale = vp->Scale;  // e.g., 2.0 on a Retina display

// Apply scale to custom geometry
ImDrawList* dl = ImGui::GetWindowDrawList();
dl->AddCircle(
    ImVec2(100, 100) * scale, 
    10.0f * scale, 
    ImGui::GetColorU32(ImGuiCol_Text)
);

ImGui::Render();

Summary

  • Enable platform DPI awareness using backend helpers like ImGui_ImplWin32_EnableDpiAwareness() or window flags like SDL_WINDOW_ALLOW_HIGHDPI.
  • Activate ImGuiConfigFlags_ViewportsEnable to allow per‑monitor DPI tracking across multiple displays.
  • Use ConfigDpiScaleFonts and ConfigDpiScaleViewports (Docking branch) to automate font atlas rebuilding and UI scaling.
  • Access DisplayFramebufferScale (global) or Viewport::Scale (per‑window) to adjust custom rendering coordinates.
  • Manually scale ImGuiStyle values if automatic viewport scaling is disabled.

Frequently Asked Questions

How do I check the current DPI scale at runtime?

Read ImGui::GetIO().DisplayFramebufferScale.x for the global scale, or call ImGui::GetWindowViewport()->Scale for the specific viewport your window occupies. Both values represent the ratio between logical and physical pixels, typically returning 1.0 for standard displays and 2.0 for Retina or 4K monitors with 200% scaling.

Why do my fonts appear blurry on high‑DPI displays?

Blurry fonts usually indicate that the font atlas was built at a low resolution before the DPI scale was applied. Enable io.ConfigDpiScaleFonts = true (Docking branch) to trigger automatic font atlas rebuilding with the correct pixel size. Alternatively, manually rebuild your fonts using ImGui::GetIO().Fonts->AddFontFromFileTTF() with a size multiplied by DisplayFramebufferScale.x.

Can I use DPI scaling with the master branch (non‑Docking)?

Yes, but with limitations. The master branch supports DisplayFramebufferScale and manual scaling, but lacks ConfigDpiScaleFonts and ConfigDpiScaleViewports. You must manually adjust style sizes and font scales when the DPI changes, as the automatic per‑monitor viewport scaling requires the multi‑viewport system present in the Docking branch.

Do I need to change my manifest file on Windows?

No. Calling ImGui_ImplWin32_EnableDpiAwareness() from imgui_impl_win32.cpp (or invoking SetProcessDpiAwarenessContext directly) enables DPI awareness programmatically without requiring a manifest. This is the recommended approach for Dear ImGui applications to avoid deployment complications.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →