Dear ImGui

repository·master·Indexed 13 days ago

https://github.com/ocornut/imgui

A bloat-free, immediate mode graphical user interface library for C++ designed for content creation tools, debuggers, and visualization tools. It is renderer-agnostic, outputting vertex buffers and command lists for integration into 3D applications and game engines. Supports a wide range of backends including DirectX, OpenGL, Vulkan, Metal, SDL2, GLFW, and Win32.

Tokens
23.5K
Snippets
60
Records
109
Agent score
96%

What's inside Dear ImGui

  1. What is Dear ImGui and when to use it

    master

    Dear ImGui is a bloat-free, fast, and portable graphical user interface library for C++. It is designed for content creation tools and visualization/debug tools rather than consumer-facing end-user interfaces.

    It is particularly suited for:

    • Game engine tooling
    • Real-time 3D applications
    • Fullscreen or embedded applications
    • Console platforms with non-standard OS features

    Key Characteristics:

    • Renderer Agnostic: It outputs optimized vertex buffers that you can render in your own 3D pipeline.
    • Self-contained: No external dependencies.
    • Immediate Mode (IMGUI): Minimizes state synchronization and UI-related state storage on the user side.
    • Limitations: It does not support full internationalization (RTL, bidirectional text, text shaping) or accessibility features.
  2. Explore Dear ImGui example applications

    master

    The examples/ folder contains standalone, ready-to-build applications for various platforms and graphics APIs. These examples demonstrate how to integrate Dear ImGui with different backends (e.g., GLFW, SDL, Win32) and renderers (e.g., OpenGL, DirectX, Vulkan, Metal, WebGPU).

    Key Recommendations:

    • For Modern Graphics: If your engine uses modern OpenGL (shaders, VBO, VAO), WebGL, or GL3+, use the opengl3 examples (e.g., example_glfw_opengl3 or example_sdl2_opengl3). Avoid opengl2 examples as they use a legacy fixed pipeline that can conflict with modern graphics states.
    • For Learning the API: Once you have a working integration, run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp to see the full range of available end-user API features.
    • For Testing: Use example_null to quickly test the compilation of core ImGui files in a headless environment without graphics output.
  3. Use the Dynamic Fonts system (v1.92+)

    master

    Starting with version 1.92, Dear ImGui introduced a dynamic font system. This requires a backend that supports the ImGuiBackendFlags_HasTextures flag.

    Key Benefits:

    • No pre-defined glyph ranges needed: Users of icons, Asian, or non-English languages no longer need to specify glyph ranges ahead of time, saving memory and loading time.
    • On-the-fly scaling: You can use PushFont(nullptr, new_size) at any time to change the font size.
    • Portable updates: Scaling fonts no longer requires backend-specific texture re-upload calls; the system handles it more portably.
    • Immediate pixel writing: Makes packing custom rectangles more convenient.
  4. Use FreeType for font rasterization

    master
    While ImGui defaults to stb_truetype, you can use the implementation in misc/freetype/ to build a font atlas/rasterizer using FreeType. This is recommended if you need better rasterization quality, particularly for small font sizes.
  5. Manage mouse cursor latency and software rendering

    master

    Dear ImGui typically does not introduce significant lag, but there is a perceived difference between hardware-accelerated OS cursors and software-rendered UI content.

    To visualize this difference or mitigate the 'disconnect' feeling, you can enable the io.MouseDrawCursor flag. This instructs Dear ImGui to draw the mouse cursor using the regular graphics API.

    Best Practice: Since rendering a software cursor at 60 FPS can feel sluggish, it is often better to enable io.MouseDrawCursor only when an interactive drag is in progress rather than all the time.

  6. How Dear ImGui works (IMGUI Paradigm)

    master

    Dear ImGui follows the Immediate Mode GUI (IMGUI) paradigm. Unlike traditional retained-mode interfaces, it aims to minimize superfluous state duplication and synchronization.

    How it handles rendering:

    • It does not touch your GPU or graphics driver directly.
    • It outputs vertex buffers and command lists (draw call batches).
    • You are responsible for taking these buffers and rendering them using your application's graphics API.
    • Because it is decoupled from the graphics state, you can call ImGui functions anywhere in your program loop (e.g., in the middle of an algorithm or your own rendering process).
  7. Note on Gamma Correct Blending with FreeType

    master

    FreeType assumes blending occurs in linear space rather than gamma space.

    To achieve correct visual results when using imgui_freetype:

    1. Use an sRGB color space.
    2. Convert to linear space in your pixel shader output.

    Warning: Default Dear ImGui styles may be impacted by this change; you may need to tweak alpha values to compensate.

  8. How the ID Stack and Label system works

    master

    Dear ImGui uses a unique ID system to track widget state (like focus or whether a tree node is open). IDs are not just the labels you see; they are hashes computed from the widget's label and its position in the ID stack (the 'path' of parent windows, tree nodes, etc.).

    Common Pitfalls:

    • ID Collisions: Using the same label for multiple widgets in the same scope (e.g., two buttons named "OK" in the same window) causes a collision. Interacting with one will trigger the other.
    • Empty Labels: Using an empty label "" is equivalent to using the label of the parent widget, which often causes collisions with the parent itself.

    Key Concepts:

    • ID Scope: IDs are implicitly scoped within their host window or tree node. Two widgets with the same label in different windows will have different IDs.
    • ID Stack: You can manipulate the stack using PushID() and PopID() to create unique namespaces for widgets, which is essential when creating widgets inside loops.
    • Debugging: Use ImGui::ShowIDStackToolWindow() to visualize the intermediate values and hashes used to create a unique ID.
    // Example of solving ID collisions in a loop using PushID
    for (int i = 0; i < 100; i++)
    {
        ImGui::PushID(i); // Push index to the stack
        ImGui::Button("Click"); // ID = hash of (..., i, "Click")
        ImGui::PopID();
    }
    
    // Example of solving ID collisions using string suffixes
    ImGui::Button("Play##1"); // Label = "Play", ID = hash of (..., "Play##1")
    ImGui::Button("Play##2"); // Label = "Play", ID = hash of (..., "Play##2")
  9. Create custom glyph ranges with ImFontGlyphRangesBuilder

    master

    Since version 1.92, specifying glyph ranges is often unnecessary with up-to-date backends. However, if you need to build a specific set of characters (e.g., only the characters used in a specific game script), use ImFontGlyphRangesBuilder.

    Workflow:

    1. Create an ImFontGlyphRangesBuilder.
    2. Add text via AddText() or specific characters via AddChar().
    3. Optionally add existing ranges via AddRanges().
    4. Call BuildRanges() to generate the ImVector<ImWchar>.
    5. Pass the resulting data to AddFontFromFileTTF().
    6. Call io.Fonts->Build() while the ranges vector is still in scope.
    ImVector<ImWchar> ranges;
    ImFontGlyphRangesBuilder builder;
    builder.AddText("Hello world");
    builder.AddChar(0x7262);
    builder.AddRanges(io.Fonts->GetGlyphRangesJapanese());
    builder.BuildRanges(&ranges);
    
    io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, nullptr, ranges.Data);
    io.Fonts->Build(); // 'ranges' must remain in scope
  10. Copyright and Licensing for contributions

    master

    By submitting code to Dear ImGui, you agree to the following:

    • Your code will be distributed under the Dear ImGui license.
    • You grant all transferable rights to the project maintainer, including re-licensing, modifying, and distributing the code.
    • You assign copyright to the project maintainer.
    • Do not modify any copyright statements in files within your PR.
  11. Multi-threading considerations in Dear ImGui

    master

    A single Dear ImGui context is not thread-safe for parallel use.

    Common Scenarios:

    • Parallel Debugging: If you need to use the same context across parallel tasks for debugging, you must use a lock (mutex).
    • Main Thread Submission / Render Thread: If you submit UI commands on a main thread but render them on a dedicated thread, you must stage ImDrawData and texture requests. Refer to ImDrawDataSnapshot and ImTextureQueue in the imgui_threaded_rendering project.
    • Multiple Contexts: If you use multiple Dear ImGui contexts across different threads, you must #define GImGui as a Thread Local Storage (TLS) variable. To display multiple contexts simultaneously, consider using imgui_multicontext_compositor.
  12. Configure 32-bit indices for Allegro 5

    master

    By default, Dear ImGui outputs 16-bit vertex indices. Because Allegro 5 does not support 16-bit indices natively, you must enable 32-bit indices to avoid manual conversion overhead.

    You can enable 32-bit indices by using the provided imconfig_allegro5.h file and pointing the IMGUI_USER_CONFIG preprocessor macro to it. The backend supports both 16-bit and 32-bit indices, but 32-bit indices are slightly faster as they bypass manual conversion.

    /* Use the IMGUI_USER_CONFIG preprocessor option to point to imconfig_allegro5.h */