How to Include Dear ImGui in a C++ Project: Complete Integration Guide

Dear ImGui is a self-contained immediate-mode GUI library that you can embed into any C++ project by adding the core source files (imgui*.h and imgui*.cpp) to your build system and selecting appropriate platform and renderer backends from the backends/ folder.

Dear ImGui, maintained in the ocornut/imgui repository, is a bloat-free graphical user interface library designed for C++ developers who need fast, iterative UI tooling. Because the library carries no external runtime dependencies, you can include Dear ImGui in a C++ project by simply compiling the source files directly alongside your application code. This guide walks through the exact file structure, backend selection, and initialization sequence required for production-ready integration.

Core Architecture and File Structure

Before integrating, it helps to understand how Dear ImGui separates concerns between the UI logic and system-specific implementation.

The library consists of three conceptual layers:

This architecture allows you to mix any platform backend with any renderer backend, enabling integration with virtually any existing engine or framework.

Essential Files for Integration

To include Dear ImGui in a C++ project, add these files to your build system:

imgui.h
imgui.cpp
imgui_draw.cpp
imgui_tables.cpp
imgui_widgets.cpp
imgui_demo.cpp       // Optional: contains ImGui::ShowDemoWindow()
imgui_internal.h     // Included by .cpp files, do not compile separately

The imgui.h header declares the public API, while the .cpp files implement the immediate-mode logic, widget rendering, and table systems. The imgui_demo.cpp file is optional but recommended for learning the API.

Step-by-Step Integration Process

Follow these steps to integrate Dear ImGui into your existing C++ codebase.

1. Select and Add Backend Files

Choose one platform backend and one renderer backend based on your target OS and graphics API. For example:

Include both header and implementation files in your compiler's source list.

2. Initialize the ImGui Context

After creating your OS window and graphics device, create the ImGui context once:

#include "imgui.h"
// ... include your selected backend headers

IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();  // or ImGui::StyleColorsLight();

ImGui::CreateContext() allocates the internal state structure, while ImGui::GetIO() exposes configuration flags and input/output references.

3. Initialize Platform and Renderer Backends

Call the initialization functions for your selected backends, passing native handles:

// Win32 + DX11 example
ImGui_ImplWin32_Init(hwnd);                      // HWND from Windows API
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);

For GLFW and OpenGL 3:

ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130");

4. Implement the Per-Frame Loop

Inside your main loop, wrap your UI code with the following sequence:

// Start the frame
ImGui_ImplDX11_NewFrame();      // or ImGui_ImplOpenGL3_NewFrame()
ImGui_ImplWin32_NewFrame();     // or ImGui_ImplGlfw_NewFrame()
ImGui::NewFrame();

// Build UI
ImGui::Begin("My Tool");
ImGui::Text("Application average %.3f ms/frame", 1000.0f / ImGui::GetIO().Framerate);
if (ImGui::Button("Save"))
    save_data();
ImGui::End();

// Finish the frame
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());  // or OpenGL equivalent

This sequence mirrors the implementation in imgui.cpp, where NewFrame() prepares the draw list and Render() finalizes the ImDrawData structure for the backend.

5. Shutdown Cleanup

When closing your application, reverse the initialization order:

ImGui_ImplDX11_Shutdown();      // or ImGui_ImplOpenGL3_Shutdown()
ImGui_ImplWin32_Shutdown();     // or ImGui_ImplGlfw_Shutdown()
ImGui::DestroyContext();

Practical Implementation Examples

Win32 and DirectX 11 Integration

This example demonstrates the minimal setup for a Windows desktop application:

#include <d3d11.h>
#include <windows.h>
#include "imgui.h"
#include "backends/imgui_impl_win32.h"
#include "backends/imgui_impl_dx11.h"

// Global device pointers (initialize these in your D3D11 setup)
extern ID3D11Device*            g_pd3dDevice;
extern ID3D11DeviceContext*     g_pd3dDeviceContext;
extern HWND                     g_hWnd;
extern ID3D11RenderTargetView*  g_mainRenderTargetView;
extern IDXGISwapChain*          g_pSwapChain;

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    // ... Create window and initialize Direct3D 11 ...
    
    // Setup Dear ImGui
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    ImGui::StyleColorsDark();
    
    // Setup Platform/Renderer backends
    ImGui_ImplWin32_Init(g_hWnd);
    ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
    
    // Main loop
    bool done = false;
    while (!done)
    {
        // Poll and handle messages (input, resize, etc.)
        MSG msg;
        while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
            if (msg.message == WM_QUIT)
                done = true;
        }
        if (done)
            break;
            
        // Start the Dear ImGui frame
        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();
        ImGui::NewFrame();
        
        // 2. Show a simple window
        static float f = 0.0f;
        static int counter = 0;
        ImGui::Begin("Hello, world!");
        ImGui::Text("This is some useful text.");
        ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
        if (ImGui::Button("Button"))
            counter++;
        ImGui::SameLine();
        ImGui::Text("counter = %d", counter);
        ImGui::End();
        
        // Rendering
        ImGui::Render();
        const float clear_color_with_alpha[4] = { 0.45f, 0.55f, 0.60f, 1.00f };
        g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
        g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
        ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
        
        g_pSwapChain->Present(1, 0); // Present with vsync
    }
    
    // Cleanup
    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();
    
    // ... Release Direct3D resources ...
    return 0;
}

Cross-Platform GLFW and OpenGL 3 Setup

For Linux, macOS, or Windows with GLFW:

#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <GLFW/glfw3.h>

int main()
{
    // Setup GLFW
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1); // Enable vsync
    
    // Initialize OpenGL loader (gl3w, glew, or glad)
    // ...
    
    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    ImGui::StyleColorsClassic();
    
    // Setup Platform/Renderer backends
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init("#version 130");
    
    // Main loop
    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        
        // Start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();
        
        // UI Code
        ImGui::Begin("Cross-Platform Demo");
        ImGui::Text("Platform: GLFW");
        ImGui::Text("Renderer: OpenGL 3");
        static float value = 0.0f;
        ImGui::SliderFloat("Value", &value, 0.0f, 1.0f);
        ImGui::End();
        
        // Rendering
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        
        glfwSwapBuffers(window);
    }
    
    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();
    
    glfwDestroyWindow(window);
    glfwTerminate();
    
    return 0;
}

Summary

  • Dear ImGui requires no external dependencies—simply compile the core .cpp files (imgui.cpp, imgui_draw.cpp, imgui_tables.cpp, imgui_widgets.cpp) directly into your project.
  • Select matching backends from the backends/ folder: one platform backend (Win32, GLFW, SDL2) and one renderer backend (DirectX, OpenGL, Vulkan) based on your existing infrastructure.
  • Follow the initialization sequence: CreateContext() → backend Init() → per-frame NewFrame()/Render() → backend Shutdown() → DestroyContext().
  • Include imgui_demo.cpp to access ImGui::ShowDemoWindow(), which serves as interactive documentation for available widgets.

Frequently Asked Questions

What are the minimum files required to include Dear ImGui in a C++ project?

You need at minimum imgui.h, imgui.cpp, imgui_draw.cpp, imgui_tables.cpp, and imgui_widgets.cpp from the repository root, plus imgui_internal.h which is included automatically. You must also add one platform backend pair (e.g., backends/imgui_impl_glfw.h/.cpp) and one renderer backend pair (e.g., backends/imgui_impl_opengl3.h/.cpp) from the backends/ folder to handle input and graphics API integration.

Does Dear ImGui require external libraries or package managers?

No. Dear ImGui is designed as a single-header-library-style distribution with no external runtime dependencies. You do not need to link against system libraries beyond what your chosen backend requires (e.g., linking against d3d11.lib for DirectX 11 or glfw for windowing). The core library uses only the C++ standard library and OS headers.

Can I use Dear ImGui with a custom game engine or existing codebase?

Yes. Because Dear ImGui generates a platform-agnostic draw list (ImDrawData) in imgui_draw.cpp, you can integrate it with any engine by providing custom backends. If your engine uses a proprietary renderer, implement the ImGui_ImplXXX_NewFrame() and ImGui_ImplXXX_RenderDrawData() functions to translate ImGui's vertex buffers into your engine's draw calls, following the patterns in the official backend files.

How do I handle keyboard and mouse input when including Dear ImGui?

Input handling is managed by the platform backend files in the backends/ folder. Functions like ImGui_ImplWin32_NewFrame() or ImGui_ImplGlfw_NewFrame() poll the underlying windowing system and populate the ImGuiIO structure. In imgui.cpp, the NewFrame() function uses this data to determine widget interactions. You can check ImGui::GetIO().WantCaptureMouse or WantCaptureKeyboard to determine if ImGui is consuming input events, allowing you to pass remaining events to your application logic.

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 →