How to Integrate Dear ImGui with SDL: Complete Setup Guide

To integrate Dear ImGui with SDL, use the official imgui_impl_sdl2 backend for platform input handling paired with a renderer backend such as imgui_impl_opengl3 for GPU drawing, initializing both after SDL window creation and calling their NewFrame/Render functions each frame.

Dear ImGui provides production-ready backend implementations that bridge the immediate-mode UI library with SDL2. According to the ocornut/imgui source code, the integration relies on a clean separation between platform handling (window events, input, clipboard) and rendering (OpenGL, Vulkan, DirectX), allowing you to mix and match backends based on your graphics requirements.

Architecture Overview

The SDL integration follows a two-layer backend design that keeps the core ImGui library renderer-agnostic.

Platform Layer (imgui_impl_sdl2): Handles OS window management, event polling, mouse/keyboard/gamepad input, clipboard operations, and cursor management. This backend translates SDL events into ImGui's internal input format but performs no drawing.

Renderer Layer (imgui_impl_opengl3, etc.): Issues GPU draw calls based on ImGui's generated draw lists. This handles shader compilation, vertex buffer management, and the actual rasterization of UI elements.

This separation means you can swap SDL for GLFW or Win32 by changing only the platform backend, or switch from OpenGL to Vulkan by changing only the renderer backend without modifying your application logic.

Step-by-Step Implementation

Follow these steps to create a minimal SDL2 + OpenGL3 + Dear ImGui application. The example mirrors the official reference located at examples/example_sdl2_opengl3/main.cpp.

Step 1: Initialize SDL and Create the OpenGL Context

First, initialize SDL with video and controller support, configure OpenGL attributes, and create the window and context.

#include <SDL.h>
#include <SDL_opengl.h>
#include "imgui.h"
#include "backends/imgui_impl_sdl2.h"
#include "backends/imgui_impl_opengl3.h"

int main(int, char**)
{
    // Initialize SDL
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER);
    
    // Configure OpenGL 3.3 Core Profile
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

    // Create window with OpenGL context
    SDL_Window* window = SDL_CreateWindow("Dear ImGui + SDL2", 
                                          SDL_WINDOWPOS_CENTERED, 
                                          SDL_WINDOWPOS_CENTERED, 
                                          1280, 720, 
                                          SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    SDL_GLContext gl_context = SDL_GL_CreateContext(window);
    SDL_GL_MakeCurrent(window, gl_context);
    SDL_GL_SetSwapInterval(1); // Enable vsync

Step 2: Initialize the ImGui Context

Create the global ImGui context and configure the style before binding any backends.

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    
    // Set style
    ImGui::StyleColorsDark();
    // ImGui::StyleColorsClassic();

Step 3: Initialize Platform and Renderer Backends

Bind ImGui to your SDL window and OpenGL context using the backend initialization functions defined in backends/imgui_impl_sdl2.cpp and backends/imgui_impl_opengl3.cpp.

    // Initialize backends
    ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
    ImGui_ImplOpenGL3_Init("#version 330");

Key initialization details:

  • ImGui_ImplSDL2_InitForOpenGL stores the window and GL context handles and sets up platform callbacks for clipboard and cursor management.
  • ImGui_ImplOpenGL3_Init compiles the internal GLSL shaders and creates the vertex array objects (VAOs) and buffers needed for rendering.

Step 4: Implement the Main Loop

Each frame, poll SDL events, process them through the ImGui backend, build your UI, and render.

    bool done = false;
    while (!done)
    {
        // Poll and handle SDL events
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            ImGui_ImplSDL2_ProcessEvent(&event);
            if (event.type == SDL_QUIT)
                done = true;
            if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE 
                && event.window.windowID == SDL_GetWindowID(window))
                done = true;
        }

        // Start new ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplSDL2_NewFrame(window);
        ImGui::NewFrame();

        // Build your UI here
        ImGui::Begin("Hello, SDL2!");
        ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 
                    1000.0f / io.Framerate, io.Framerate);
        ImGui::End();

        // Rendering
        ImGui::Render();
        glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
        glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        // Draw ImGui data
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        
        SDL_GL_SwapWindow(window);
    }

Critical loop functions:

  • ImGui_ImplSDL2_ProcessEvent translates SDL input events (keyboard, mouse, gamepad) into ImGui's ImGuiIO structure.
  • ImGui_ImplSDL2_NewFrame updates display size, delta time, and mouse position based on SDL window state.
  • ImGui_ImplOpenGL3_RenderDrawData executes the actual GL draw calls using the vertex buffers generated by ImGui::Render().

Step 5: Cleanup Resources

Shutdown backends in reverse order and destroy SDL resources.

    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

    SDL_GL_DeleteContext(gl_context);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

Key Source Files and Functions

Understanding these specific files from the ocornut/imgui repository helps when debugging or extending the integration:

Summary

  • Dear ImGui SDL integration requires two backends: imgui_impl_sdl2 for platform input and imgui_impl_opengl3 (or Vulkan/DirectX) for rendering.
  • Initialize SDL first, then create the ImGui context, then initialize backends with ImGui_ImplSDL2_InitForOpenGL() and ImGui_ImplOpenGL3_Init().
  • Process events through ImGui_ImplSDL2_ProcessEvent() in your event loop to capture input.
  • Call NewFrame functions in order (renderer first, then platform) before building UI, then ImGui::Render() followed by the renderer's RenderDrawData().
  • Cleanup in reverse initialization order to prevent memory leaks and OpenGL context errors.

Frequently Asked Questions

Can I use Dear ImGui with SDL without OpenGL?

Yes, but you must pair the SDL platform backend with a different renderer backend. Dear ImGui provides official backends for Vulkan (imgui_impl_vulkan), DirectX 11/12 (imgui_impl_dx11, imgui_impl_dx12), and Metal (imgui_impl_metal). The SDL backend handles window and input events regardless of which renderer you choose.

Why is my ImGui window not receiving mouse clicks?

Ensure you call ImGui_ImplSDL2_ProcessEvent() for every SDL event in your polling loop, and verify that ImGui_ImplSDL2_NewFrame() is called every frame before ImGui::NewFrame(). If using custom SDL event handling, confirm that SDL_Event structures are not being consumed before reaching the ImGui processor.

How do I handle high-DPI displays with SDL and ImGui?

The SDL backend in imgui_impl_sdl2.cpp automatically queries SDL_GetDisplayDPI and scales the io.DisplayFramebufferScale vector accordingly. Ensure you create your SDL window with the SDL_WINDOW_ALLOW_HIGHDPI flag, and check that your OpenGL viewport accounts for the framebuffer scale returned in ImGuiIO.

Can I integrate ImGui into an existing SDL application?

Yes. Include the backend files (imgui_impl_sdl2.cpp, your renderer backend, and core imgui.cpp) in your build system. Initialize the ImGui context and backends after your existing SDL and graphics setup. Replace your current event loop with one that calls ImGui_ImplSDL2_ProcessEvent(), and insert the NewFrame/Render calls into your existing frame update logic without removing your current rendering code.

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 →