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

TLDR: Dear ImGui handles high-DPI displays through a combination of platform-specific DPI awareness settings, IO configuration flags, and per-viewport scaling factors that automatically adjust fonts and UI geometry.

Managing DPI scaling is essential when building desktop applications that must look crisp on Retina displays and 4K monitors. The ocornut/imgui repository provides built-in mechanisms to handle high-DPI displays through framebuffer scaling and viewport-based DPI detection. This guide explains how to configure your application using the actual source implementation found in imgui.h, imgui.cpp, and the various platform backends.

Core DPI Scaling Mechanisms

Dear ImGui's approach to high-DPI support centers on three key data structures that communicate display density from the platform layer to the rendering pipeline.

DisplayFramebufferScale and FramebufferScale

The global DPI scale factor is stored in ImGuiIO::DisplayFramebufferScale (imgui.h, which represents the ratio between pixels and screen coordinates for the main display. When the multi-viewport feature is enabled, each ImGuiViewport maintains its own FramebufferScale derived from the platform window's DPI. According to the source in imgui.h, the Viewport::Scale field carries this per-monitor scaling factor, ensuring that UI geometry remains crisp when windows move between displays of different densities.

Runtime DPI Tracking

During NewFrame(), the backend updates CurrentDpiScale (imgui.cpp based on the active monitor. This value propagates to ImDrawData::FramebufferScale, which the renderer uses to calculate final pixel positions. All built-in widgets automatically respect this scale when computing sizes, so standard ImGui controls render sharply without manual intervention.

Platform-Specific DPI Awareness Setup

Before ImGui can apply scaling, the underlying platform window must report accurate DPI information. Each backend requires specific initialization to enable high-DPI support.

Windows (Win32)

For Win32 applications, call ImGui_ImplWin32_EnableDpiAwareness() before creating your window. This helper function, defined in imgui_impl_win32.cpp, invokes SetProcessDpiAwarenessContext() to declare the process as per-monitor DPI aware. Alternatively, you can call Windows API functions directly:

ImGui_ImplWin32_EnableDpiAwareness();   // Recommended helper

// Or manually:
::SetProcessDPIAware();  // System DPI aware (legacy)
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);  // Modern

SDL2

When creating your window with SDL2, pass the SDL_WINDOW_ALLOW_HIGHDPI flag and ensure Windows DPI awareness is set:

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

::SetProcessDPIAware();  // Windows-specific

GLFW

GLFW applications should enable monitor scaling and query content scale:

glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);

// Later, when needed:
float x_scale, y_scale;
glfwGetMonitorContentScale(monitor, &x_scale, &y_scale);

Configuring Automatic DPI Scaling

The docking branch provides automatic scaling through configuration flags that eliminate manual font resizing.

Enabling Auto-Scale Features

Set these fields in ImGuiIO before calling NewFrame() (found in imgui.h:

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;    // Required for per-monitor DPI
io.ConfigDpiScaleFonts = true;                        // Rebuild font atlas automatically
io.ConfigDpiScaleViewports = true;                    // Scale entire UI automatically

When ConfigDpiScaleFonts is enabled, ImGui rebuilds the font atlas using FontScaleDpi (imgui.h to match the current display density. The ConfigDpiScaleViewports flag ensures that CellPadding, FrameRounding, and other style fields in ImGuiStyle (imgui.cpp adjust automatically when monitors change.

Manual DPI Handling and Custom Rendering

For custom drawing or integrating non-ImGui resources that require pixel-perfect alignment, access the current viewport's scale factor directly:

ImGuiViewport* vp = ImGui::GetWindowViewport();
float dpiScale = vp->Scale;  // e.g., 2.0f on Retina displays

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

You can also read the global scale from io.DisplayFramebufferScale.x when ViewportsEnable is not active, though per-viewport scaling is preferred for multi-monitor setups.

Summary

  • Platform setup is required first: Call ImGui_ImplWin32_EnableDpiAwareness() for Win32 or use SDL_WINDOW_ALLOW_HIGHDPI for SDL2 before initializing ImGui.
  • Enable viewport support: Set ImGuiConfigFlags_ViewportsEnable to allow per-monitor DPI detection when windows move between displays.
  • Use automatic scaling flags: Enable ConfigDpiScaleFonts and ConfigDpiScaleViewports (docking branch only) to automatically rebuild fonts and scale UI geometry.
  • Access scale factors via Viewport: Read ImGuiViewport::Scale for custom drawing or external resource management that must match ImGui's pixel density.
  • Core implementation: Library state resides in ImGuiIO::DisplayFramebufferScale and per-viewport FramebufferScale as defined in imgui.h.

Frequently Asked Questions

Does Dear ImGui automatically detect DPI changes when moving windows between monitors?

Yes, provided you enable ImGuiConfigFlags_ViewportsEnable in the IO configuration. When this flag is set, each ImGuiViewport tracks its own Scale factor derived from the platform window's current monitor. The backend updates this value during NewFrame(), allowing the UI to adapt without manual intervention when dragging windows between displays of different densities.

Why do my fonts look blurry on high-DPI displays?

Blurry fonts occur when the font atlas is rendered at the base pixel size and then stretched by the display's scale factor. Enable io.ConfigDpiScaleFonts = true (docking branch) to automatically rebuild the font atlas with FontScaleDpi applied. This ensures glyphs render at the correct physical pixel size for the current display density, eliminating upscaling artifacts.

Do I need the docking branch to use DPI scaling?

Basic DPI scaling works in the master branch using DisplayFramebufferScale and manual font reloading. However, automatic per-monitor scaling via ConfigDpiScaleFonts and ConfigDpiScaleViewports requires the docking branch. For multi-monitor setups with different DPI values, the docking branch's viewport system is strongly recommended.

How do I scale custom OpenGL or DirectX rendering to match ImGui's DPI?

Retrieve the current scale from the active viewport and multiply your custom geometry by this factor. Access ImGui::GetWindowViewport()->Scale to get the float value (typically 1.0 for standard displays, 2.0 for Retina). Apply this multiplier to vertex positions, line thickness, and point sizes in your custom draw calls to maintain visual consistency with ImGui's scaled output.

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 →