# How to Integrate ImGui with OpenGL: Backend Setup for Modern Core Profiles

> Learn to integrate ImGui with OpenGL by setting up a core profile context and using the official backend files. Get started quickly with our clear guide.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-21

---

**TLDR:** To integrate ImGui with OpenGL, create a core-profile OpenGL context, include [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp) from the `backends/` folder, and call `ImGui_ImplOpenGL3_Init` with a matching GLSL version string before driving the frame loop with `ImGui_ImplOpenGL3_NewFrame` and `ImGui_ImplOpenGL3_RenderDrawData`.

Dear ImGui is a renderer-agnostic UI library that ships its OpenGL support as a standalone backend in the `ocornut/imgui` repository. To integrate ImGui with OpenGL, you only need the `imgui_impl_opengl3.*` renderer backend paired with a platform backend such as GLFW, SDL, or Win32. The same backend works across OpenGL 2.0 through 4.6+ by automatically detecting and enabling modern features at runtime.

## Where the OpenGL Backend Lives in ImGui

All OpenGL rendering logic lives in [`backends/imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_opengl3.cpp) and [`backends/imgui_impl_opengl3.h`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_opengl3.h). Because Dear ImGui itself is renderer-agnostic, these files handle shader compilation, vertex buffer management, and state restoration without touching the core [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) or [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) API. The repository's reference application in [`examples/example_glfw_opengl3/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_opengl3/main.cpp) demonstrates the standard integration pattern; for OpenGL 4.x you only need to adjust the context-creation window hints and the GLSL version string passed to the backend.

## Creating an OpenGL 4.x Rendering Context

Request a core profile from your windowing library before initializing ImGui. The following GLFW hints configure an OpenGL 4.5 core context:

```cpp
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // macOS
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui + OpenGL 4.5", nullptr, nullptr);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);

```

You can substitute 4.1 or 4.6 by changing the major and minor hints. The ImGui OpenGL backend does not require a specific context version beyond what your own renderer needs.

## Initializing the OpenGL Backend for ImGui

Call the platform backend first, then the renderer backend, and finally create the ImGui context.

### Linking the Platform Backend

Link [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp) (or your platform equivalent) and initialize it for OpenGL:

```cpp
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;

ImGui_ImplGlfw_InitForOpenGL(window, true);

```

### Passing the GLSL Version String

Pass a GLSL version string matching your context to `ImGui_ImplOpenGL3_Init`. For OpenGL 4.5, use `"#version 450 core"`:

```cpp
const char* glsl_version = "#version 450 core";
ImGui_ImplOpenGL3_Init(glsl_version);

```

If you pass `nullptr`, the backend attempts to infer a compatible shader version automatically. Explicit strings are recommended for OpenGL 4.x core profiles because they guarantee modern syntax such as `layout(location = ...)` inside the generated shaders. According to the `ocornut/imgui` source code, the function `ImGui_ImplOpenGL3_CreateDeviceObjects` prepends this GLSL string when assembling shader source ([`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp), lines 104-126).

## Implementing the Frame Render Loop

Each frame follows a strict sequence: platform new-frame, renderer new-frame, ImGui new-frame, UI construction, and finally drawing submission.

```cpp
while (!glfwWindowShouldClose(window))
{
    glfwPollEvents();

    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplGlfw_NewFrame();
    ImGui::NewFrame();

    // --- Your UI code ---
    ImGui::Begin("OpenGL 4.5 Demo");
    ImGui::Text("Running with OpenGL %s", glGetString(GL_VERSION));
    ImGui::End();
    // --------------------

    ImGui::Render();
    int fb_w, fb_h;
    glfwGetFramebufferSize(window, &fb_w, &fb_h);
    glViewport(0, 0, fb_w, fb_h);
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    glfwSwapBuffers(window);
}

```

`ImGui_ImplOpenGL3_RenderDrawData` consumes the draw lists produced by `ImGui::Render` and issues the actual OpenGL draw calls on your behalf.

## Automatic OpenGL 4.x Feature Detection

The same [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp) backend enables several advanced capabilities when the driver reports support, so you do not need conditional code in your application:

- **Upper-left clip origin via `glClipControl`** — When the runtime flag `HasClipOrigin` is true, `ImGui_ImplOpenGL3_SetupRenderState` automatically toggles `GL_UPPER_LEFT` clip origin behavior ([`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp), lines 55-63).
- **Sampler objects with `glBindSampler`** — If `IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER` is defined and `HasBindSampler` is set at runtime, the backend uses `ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear` and `ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest` for filtering ([`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp), lines 13-33).
- **Vertex-offset rendering via `glDrawElementsBaseVertex`** — For meshes exceeding 64k vertices, the path guarded by `IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET` is activated inside `ImGui_ImplOpenGL3_RenderDrawData` ([`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp), lines 200-207).
- **State preservation** — The backend saves and restores every piece of OpenGL state it touches, including the current VAO, VBO, shader program, blend parameters, and viewport. This makes it safe to inject into an existing OpenGL 4.x rendering pipeline without side effects.

## Build and Run a Complete GLFW Example

Here is a self-contained program that creates an OpenGL 4.5 context, initializes Dear ImGui, and runs the frame loop:

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

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    GLFWwindow* win = glfwCreateWindow(1280, 720, "ImGui + OpenGL 4.5", nullptr, nullptr);
    glfwMakeContextCurrent(win);
    glfwSwapInterval(1);

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

    ImGui_ImplGlfw_InitForOpenGL(win, true);
    const char* glsl = "#version 450 core";
    ImGui_ImplOpenGL3_Init(glsl);

    while (!glfwWindowShouldClose(win))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGui::Begin("Hello GL 4.5");
        ImGui::Text("OpenGL version: %s", glGetString(GL_VERSION));
        ImGui::End();

        ImGui::Render();
        int w, h;
        glfwGetFramebufferSize(win, &w, &h);
        glViewport(0, 0, w, h);
        glClearColor(0.12f, 0.13f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        glfwSwapBuffers(win);
    }

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();
    glfwDestroyWindow(win);
    glfwTerminate();

    return 0;
}

```

Compile the example by linking GLFW and OpenGL. On Linux, the typical command is:

```bash
g++ -std=c++17 main.cpp -Ipath/to/imgui -Ipath/to/imgui/backends \
    -lglfw -lGL -ldl -pthread -o imgui_gl45

```

## Proper Cleanup Sequence

Shutdown in the reverse order of initialization:

```cpp
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();

```

## Summary

- Integrate ImGui with OpenGL by adding [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp) and a platform backend from the `ocornut/imgui` `backends/` folder.
- Create an OpenGL core context with windowing hints for version 4.x, then pass a matching GLSL string such as `"#version 450 core"` to `ImGui_ImplOpenGL3_Init`.
- Drive each frame with `ImGui_ImplOpenGL3_NewFrame`, your platform `NewFrame`, `ImGui::NewFrame`, and finalize with `ImGui_ImplOpenGL3_RenderDrawData`.
- The backend automatically leverages OpenGL 4.x capabilities—including `glClipControl`, sampler objects, and `glDrawElementsBaseVertex`—when the driver supports them.
- State restoration in [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp) ensures the backend does not corrupt your existing renderer state.

## Frequently Asked Questions

### Do I need a separate backend for OpenGL 4.x?

No. The same `imgui_impl_opengl3` backend works with any OpenGL version from 2.0 through 4.6 and newer. It detects runtime capabilities such as `HasBindSampler` and `HasClipOrigin`, and selects appropriate shader paths inside `ImGui_ImplOpenGL3_CreateDeviceObjects`, so a single codebase covers all versions.

### What GLSL version should I pass to `ImGui_ImplOpenGL3_Init`?

Pass a string that matches your context, for example `"#version 450 core"` for OpenGL 4.5. If you pass `nullptr`, the backend attempts to infer a compatible version, but explicit strings are safer for core profiles because they guarantee modern syntax like explicit `layout(location)` qualifiers.

### Will the ImGui backend interfere with my custom OpenGL state?

No. According to the `ocornut/imgui` source code, [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp) saves and restores every state object it touches, including the current VAO, VBO, shader program, blend parameters, and viewport. This makes it safe to call `ImGui_ImplOpenGL3_RenderDrawData` inside an existing OpenGL 4.x rendering pipeline.

### Can I use this backend with OpenGL ES or older OpenGL 2.0?

Yes. The backend is not limited to OpenGL 4.x; it supports OpenGL ES 2.0/3.0 and desktop OpenGL 2.0+. Feature flags such as `IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET` and `IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER` are enabled only when the driver version or extensions indicate support, allowing the same code to run across hardware generations.