Difference Between ImTextureID and ImTextureRef in Dear ImGui
ImTextureID is a low-level 64-bit backend handle (ImU64) representing a GPU texture, while ImTextureRef is a higher-level wrapper struct introduced in v1.92.0 that can hold either an ImTextureID or a pointer to internal ImTextureData, allowing ImGui to distinguish between user textures and font atlas textures.
Understanding the difference between ImTextureID and ImTextureRef is essential when working with custom rendering in Dear ImGui. These two identifiers represent different abstraction layers for GPU texture management within the ocornut/imgui codebase, specifically defined in imgui.h around lines 320-374. While both serve to reference textures during immediate-mode GUI rendering, they evolved separately to solve distinct architectural challenges between backend-specific resource handles and ImGui's internal texture atlas system.
What Is ImTextureID?
ImTextureID is the low-level, backend-specific identifier that ImGui uses to communicate with your graphics API. According to the source code in imgui.h, it is defined as:
typedef ImU64 ImTextureID;
This 64-bit unsigned integer can store either a pointer value or an integer handle, depending on your graphics backend. For example, OpenGL backends typically cast GLuint texture names to ImTextureID, while Vulkan backends might store VkDescriptorSet handles.
Version History and Type Safety
Prior to v1.91.4 (released 2024-10-08), ImTextureID was defined as void*. The change to ImU64 was made to support 64-bit texture identifiers on 32-bit platforms, ensuring that high-range GPU handles do not get truncated. This modification affects how you cast your native texture handles when integrating custom backends.
What Is ImTextureRef?
ImTextureRef is a higher-level wrapper structure introduced in v1.92.0 (2025-06-11) to unify how ImGui handles both user-provided textures and internal font atlas textures. Unlike the plain ImTextureID, this struct can distinguish between a raw GPU handle and a pointer to ImTextureData (the internal atlas representation).
In imgui.h, the structure contains two key members:
_TexData: A pointer toImTextureDatafor internal atlas textures_TexID: The low-levelImTextureIDfor user-provided GPU handles
This dual nature allows ImGui to store references to textures that may not yet be uploaded to the GPU—such as font atlas textures that are created during the first frame—while maintaining compatibility with the classic ID-only workflow.
Key Architectural Differences
The distinction between these types becomes clear when examining their roles in the rendering pipeline:
| Feature | ImTextureID | ImTextureRef |
|---|---|---|
| Storage | Plain 64-bit value (ImU64) |
Struct with _TexData and _TexID members |
| Abstraction Level | Backend-specific GPU handle | High-level wrapper supporting internal atlas data |
| Primary Use | Passed to drawing functions when you already have a GPU handle | Used by all v1.92.0+ API functions accepting textures |
| Atlas Support | Cannot represent internal atlas textures directly | Can reference ImTextureData for font atlases |
| Conversion | Extracted via GetTexID() |
Created via ImTextureRefFromID() or constructor |
Importantly, there is no implicit conversion from ImTextureID to ImTextureRef in the reverse direction because an ImTextureRef may hold atlas data that cannot be represented by a plain ID. The rendering backend ultimately receives an ImTextureID when ImDrawCmd structures are processed, but the command itself stores an ImTextureRef as implemented in imgui_draw.cpp.
Working with Textures in Practice
Classic Usage with Raw IDs
If you are maintaining legacy code or working with custom backends that predate v1.92.0, you interact directly with the low-level identifier:
// Cast your native handle to ImTextureID
ImTextureID my_tex_id = (ImTextureID)(size_t)my_opengl_texture;
ImGui::Image(my_tex_id, ImVec2(128, 128));
Modern Usage with ImTextureRef
Since v1.92.0, all user-facing functions that previously accepted ImTextureID now accept ImTextureRef. Wrap your existing IDs using the helper function:
// Wrap the raw ID in a reference
ImTextureRef tex_ref = ImTextureRefFromID(my_tex_id);
ImGui::Image(tex_ref, ImVec2(128, 128));
Extracting Backend Handles
When implementing a custom render loop in your backend, extract the low-level ID using the accessor method:
// Inside your draw command processing loop
ImTextureID id_to_pass = draw_cmd->TextureId.GetTexID();
backend_bind_texture(id_to_pass);
The GetTexID() method safely handles both user textures and atlas textures, returning the appropriate ImTextureID for the backend to bind.
Accessing the Font Atlas
The internal font atlas stores its texture as an ImTextureRef, illustrating the "internal texture" use case:
ImFontAtlas* atlas = ImGui::GetIO().Fonts;
ImTextureRef atlas_ref = atlas->TexID; // Already an ImTextureRef
ImGui::Image(atlas_ref, ImVec2(256, 64));
Internal Implementation Details
The validation and debugging of these identifiers occurs in imgui_internal.h, which provides utilities such as DebugTextureIDToU64() around line 3853 for converting texture references to a consistent 64-bit representation for debugging purposes.
When inspecting imgui_draw.cpp, you will find that ImDrawCmd structures now store ImTextureRef rather than raw ImTextureID. This change allows the rendering pipeline to defer texture handle resolution until the actual draw command is executed, supporting ImGui's ability to rebuild font atlases dynamically without invalidating existing draw lists.
Summary
- ImTextureID is a backend-specific 64-bit handle (
ImU64) changed fromvoid*in v1.91.4 to support 64-bit identifiers on 32-bit platforms. - ImTextureRef is a wrapper struct introduced in v1.92.0 containing
_TexDataand_TexIDmembers, enabling ImGui to reference both user textures and internal atlas data. - Convert from
ImTextureIDtoImTextureRefusingImTextureRefFromID(), and extract the raw ID viaGetTexID()when binding textures in your backend. ImDrawCmdstoresImTextureRefto support deferred texture resolution and dynamic atlas updates.- All new code should use
ImTextureReffor API compatibility with v1.92.0 and later.
Frequently Asked Questions
Can I still use ImTextureID directly in new ImGui code?
While the underlying ImTextureID type remains valid for backend implementation, the public API since v1.92.0 expects ImTextureRef for all texture parameters in functions like ImGui::Image(). You should wrap your existing ImTextureID values using ImTextureRefFromID() when calling these functions. The type definition in imgui.h ensures backward compatibility for backend code that binds textures, but user code must adapt to the new wrapper type.
How do I convert my existing ImTextureID to ImTextureRef?
Use the ImTextureRefFromID() helper function defined in imgui.h, or construct an ImTextureRef directly by passing your ID to the constructor:
ImTextureID my_id = (ImTextureID)gl_texture;
ImTextureRef ref = ImTextureRefFromID(my_id); // or ImTextureRef(my_id)
There is no built-in conversion from ImTextureRef back to ImTextureID except through the GetTexID() method, which should only be called by rendering backends when processing draw commands.
Why did ImGui change ImTextureID from void* to ImU64 in v1.91.4?
The change to ImU64 (64-bit unsigned integer) in v1.91.4 ensures that 64-bit texture handles—common in modern graphics APIs like Vulkan and DirectX 12—are not truncated when running on 32-bit platforms. Previously defined as void*, the pointer type could only hold 32 bits on x86 architectures, causing collisions or invalid handles when the upper 32 bits of a GPU descriptor were significant. This modification maintains full precision across all supported platforms.
When should I use ImTextureRef::GetTexID()?
Call GetTexID() only when implementing a custom rendering backend that processes ImDrawCmd structures. This method extracts the low-level ImTextureID that your graphics API (OpenGL, Vulkan, DirectX, etc.) needs to bind the actual GPU resource. According to the implementation in imgui_internal.h, this method handles both cases: when the ref contains a raw ID it returns it directly, and when it references internal atlas data it extracts the appropriate backend handle from the ImTextureData structure.
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 →