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:
-
Core Library: Provides the immediate-mode API (
ImGui::Begin(),ImGui::Button(), etc.) and maintains UI state inimgui.cpp,imgui_draw.cpp,imgui_tables.cpp, andimgui_widgets.cpp. These files know nothing about how pixels reach the screen. -
Platform Backend: Bridges OS windowing and input events (mouse, keyboard, gamepad) into ImGui's internal format. Files like
backends/imgui_impl_win32.cpporbackends/imgui_impl_glfw.cpphandle window message loops and input polling. -
Renderer Backend: Translates ImGui's draw commands (
ImDrawData) into GPU API calls. Implementations such asbackends/imgui_impl_dx11.cpporbackends/imgui_impl_opengl3.cppupload vertex buffers and issue draw calls.
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:
- Win32 + DirectX 11: Add
backends/imgui_impl_win32.h/.cppandbackends/imgui_impl_dx11.h/.cpp - Cross-platform OpenGL: Add
backends/imgui_impl_glfw.h/.cppandbackends/imgui_impl_opengl3.h/.cpp
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
.cppfiles (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()→ backendInit()→ per-frameNewFrame()/Render()→ backendShutdown()→DestroyContext(). - Include
imgui_demo.cppto accessImGui::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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →