# How Dear ImGui's Immediate Mode GUI Paradigm Differs from Retained-Mode UI Toolkits

> Discover how Dear ImGui's immediate mode GUI bypasses persistent objects by recreating UI elements each frame, simplifying layout and interaction unlike retained-mode toolkits.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: deep-dive
- Published: 2026-07-15

---

**Dear ImGui implements an immediate mode GUI where UI elements are recreated and processed every frame through direct function calls that handle both layout and interaction in a single pass, eliminating persistent widget objects.**

The **immediate mode GUI** architecture in the `ocornut/imgui` repository fundamentally reimagines how user interfaces are constructed and rendered. Unlike traditional toolkits that maintain long-lived object hierarchies, Dear ImGui rebuilds the entire interface from scratch each frame using stateless function calls. This approach places UI logic directly in the application loop while the library handles efficient batching and rendering behind the scenes.

## Core Principles of Immediate Mode GUI

### Stateless Rendering Without Persistent Objects

In Dear ImGui's immediate mode paradigm, functions like `ImGui::Button("OK")` do not instantiate persistent widget objects. Instead, each call queries the current input state, determines hover and click status, updates minimal internal state, and immediately returns a boolean result. According to the source code in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), this design eliminates the need for a separate UI object model that exists across frames.

### Single-Frame Data Lifecycle

All UI data in the immediate mode GUI lives only for the duration of the current frame. If your application needs to persist values—such as a slider's current position—that state must be stored in your own variables and passed back to ImGui on subsequent frames. The library maintains only essential navigation and focus state internally, as defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h).

### Implicit UI Hierarchy

Rather than constructing a tree of widget objects that persist in memory, the immediate mode GUI hierarchy is implicitly defined by the order of function calls each frame. When you call `ImGui::Begin("Window")` followed by `ImGui::SliderFloat()`, the nesting structure exists only for that specific frame's execution context.

## Immediate Mode vs. Retained Mode: Key Differences

Understanding the architectural contrast between these paradigms clarifies why Dear ImGui adopts its specific approach:

- **Widget Lifecycle**: **Immediate mode** creates, processes, and destroys UI elements each frame with no long-lived objects, while **retained mode** instantiates widgets once that persist until explicitly destroyed.

- **Event Handling**: **Immediate mode** polls events directly inside widget functions that return interaction flags immediately, whereas **retained mode** dispatches events to existing objects via callbacks or listener patterns.

- **State Storage**: **Immediate mode** requires the application to store all persistent state; ImGui keeps only minimal internal data for navigation and focus management. **Retained mode** embeds state directly within widget objects (text content, selection ranges, etc.).

- **Performance Characteristics**: Despite rebuilding the UI every frame, Dear ImGui does not issue a draw call per widget. As implemented in [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp), the library batches geometry into vertex buffers and emits a small list of draw commands. This avoids the "hammering the GPU" pitfall mentioned in [`docs/README.md`](https://github.com/ocornut/imgui/blob/main/docs/README.md). Retained-mode engines may batch internally but often require full scene graph traversal each frame.

- **API Complexity**: **Immediate mode** offers a simpler API where you write UI code inline where needed, while **retained mode** requires maintaining separate widget objects and hooking them up to data models.

## Implementation Architecture in Dear ImGui

The immediate mode GUI implementation spans several key files in the repository:

- **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)**: Exposes the public API with immediate-mode functions including `ImGui::Begin()`, `ImGui::Button()`, and `ImGui::SliderFloat()`.

- **[`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp)**: Contains the core implementation of the UI state machine, input handling logic, and the draw-list generation that translates immediate calls into renderable data.

- **[`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp)**: Handles vertex buffer construction and draw-list batching, ensuring that multiple widget calls collapse into efficient GPU commands.

- **[`backends/imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_opengl3.cpp)**: Demonstrates how renderer backends consume ImGui's draw data and submit it to the GPU, illustrating the separation between immediate-mode UI logic and actual rendering.

## Practical Implementation Examples

The following pattern demonstrates the immediate mode GUI inside a typical game loop:

```cpp
// Example: simple window with a button and a slider
bool show_demo = true;
float value = 0.0f;

ImGui::Begin("Demo Window", &show_demo);           // Re-creates the window each frame
if (ImGui::Button("Press Me")) {                  // Returns true on click
    // Handle click immediately
    value = 0.0f;
}
ImGui::SliderFloat("Value", &value, 0.0f, 1.0f); // Reads/writes the external variable
ImGui::End();                                      // Window layout is finalized

```

This example shows how the immediate mode GUI processes interaction immediately within the same frame:

```cpp
// Immediate-mode style UI inside a game loop
while (running) {
    // 1. Gather input, start new ImGui frame
    ImGui_ImplXXX_NewFrame();
    ImGui::NewFrame();

    // 2. Build UI (the immediate-mode pass)
    ShowDemoWindow(&show_demo);

    // 3. Render: ImGui builds draw-list, then back-end draws it
    ImGui::Render();
    ImGui_ImplXXX_RenderDrawData(ImGui::GetDrawData());

    // 4. Swap buffers, etc.
}

```

In this loop, `ImGui::NewFrame()` resets internal state, your UI code executes the immediate mode pass, and `ImGui::Render()` generates the batched draw data that the backend submits to the GPU.

## Summary

- Dear ImGui uses an **immediate mode GUI** where widgets exist only for the current frame and are recreated through function calls every loop iteration.

- **State management** is the application's responsibility; the library queries external variables rather than owning persistent widget state.

- The **API design** eliminates boilerplate by handling layout and interaction in a single pass without requiring object instantiation or event listener registration.

- Despite the per-frame reconstruction, **rendering remains efficient** through vertex batching in [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp), not individual draw calls per widget.

- The architecture is defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), with platform-specific rendering handled by backend implementations like [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp).

## Frequently Asked Questions

### Does immediate mode GUI mean Dear ImGui redraws every pixel individually each frame?

No. While the UI is logically rebuilt every frame through function calls, Dear ImGui batches all geometry into vertex buffers and emits a minimal set of draw commands. As noted in [`docs/README.md`](https://github.com/ocornut/imgui/blob/main/docs/README.md), this distinction prevents the "hammering the GPU" behavior associated with naive immediate mode rendering.

### Where is widget state stored in an immediate mode GUI?

Widget state is stored in your application variables, not inside ImGui objects. When calling `ImGui::SliderFloat("Value", &value, 0.0f, 1.0f)`, the library reads from and writes to your `value` variable directly. The only state ImGui retains internally involves navigation, focus management, and temporary frame data.

### How does event handling work without persistent widget objects?

Events are polled synchronously inside the widget function. When you call `ImGui::Button("OK")`, it immediately checks the current input state and returns `true` if clicked during that frame. There are no callbacks or event queues; interaction results are available instantly as return values.

### Can immediate mode GUIs handle complex UI hierarchies efficiently?

Yes. Dear ImGui manages complex layouts through stack-based context tracking in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp). While the hierarchy is rebuilt each frame, the library maintains internal stacks for window clipping, layout positioning, and ID hashing that enable efficient processing of nested containers without persistent scene graphs.