ImTextureID vs ImTextureRef in Dear ImGui: Complete API Reference and Migration Guide

ImTextureID is a low-level 64-bit GPU handle, while ImTextureRef is a higher-level wrapper struct introduced in v1.92.0 that can represent either a user texture ID or an internal atlas texture, allowing Dear ImGui to distinguish between texture sources.

Understanding the distinction between ImTextureID and ImTextureRef is essential when working with textures in Dear ImGui. As of version 1.92.0, the library migrated from raw texture handles to a more flexible reference system that supports deferred texture uploads and internal font atlas management. This guide explains the technical differences between these two types and shows you how to migrate your code using actual implementation details from the ocornut/imgui repository.

Understanding ImTextureID: The Low-Level Backend Handle

ImTextureID represents a raw, backend-specific GPU resource identifier. According to the source code in imgui.h (lines 320-374), it is defined as:

typedef ImU64 ImTextureID;

This definition changed from void* to ImU64 in v1.91.4 (October 2024) to support 64-bit texture identifiers on 32-bit platforms. The type can hold various backend-specific handles, including:

  • OpenGL: GLuint texture IDs
  • Vulkan: VkDescriptorSet or VkImageView handles
  • DirectX: ID3D11ShaderResourceView* pointers
  • SDL: SDL_Texture* pointers

The rendering backends in imgui_draw.cpp use this value directly to bind the correct GPU resource during draw command execution.

Understanding ImTextureRef: The High-Level Wrapper

ImTextureRef is a lightweight struct introduced in v1.92.0 (June 2025) that wraps texture identification with additional metadata. As defined in imgui.h, the struct contains two members:

  • _TexData: A pointer to ImTextureData (for internal atlas textures)
  • _TexID: An ImTextureID value (for user-provided textures)

This dual representation allows Dear ImGui to store references to textures that may not yet be uploaded to the GPU, such as font atlas textures created during initialization but uploaded later. The ImDrawCmd structure in the rendering pipeline now stores ImTextureRef instead of raw ImTextureID values.

Key Differences: ImTextureID vs ImTextureRef

The architectural split between these types serves distinct purposes in the rendering pipeline:

Abstraction Level

  • ImTextureID: A plain 64-bit value (ImU64) that backends interpret as a native GPU handle.
  • ImTextureRef: A semantic wrapper that distinguishes between user textures and built-in atlas textures managed by the font system.

Conversion Directionality

  • You can obtain an ImTextureID from an ImTextureRef via the GetTexID() method.
  • There is no implicit conversion from ImTextureID to ImTextureRef because a reference may hold atlas data that cannot be represented by a plain ID.

API Surface

  • Functions like ImGui::Image() and ImGui::ImageButton() now accept ImTextureRef as of v1.92.0, replacing the previous ImTextureID parameters.
  • Backend implementations still operate on ImTextureID extracted from the reference when processing draw commands.

Converting Between Types

Dear ImGui provides explicit conversion utilities to move between these representations safely.

Converting from ImTextureID to ImTextureRef:

ImTextureID my_gpu_handle = (ImTextureID)(size_t)my_opengl_texture;
ImTextureRef tex_ref = ImTextureRefFromID(my_gpu_handle);
// Or via direct construction:
ImTextureRef tex_ref2(my_gpu_handle);

Extracting the raw ID for backend operations:

ImTextureID id_to_bind = tex_ref.GetTexID();
// Pass to backend-specific rendering code
backend_render_texture(id_to_bind);

The GetTexID() method safely extracts the underlying ImTextureID when the reference stores user texture data. According to imgui_internal.h (line 3853), internal helpers like DebugTextureIDToU64 ensure consistent handling across different backend architectures.

Practical Code Examples

Legacy Usage (Pre-v1.92)

The classic approach still functions for backward compatibility, though it bypasses the atlas management features:

// Cast your native texture 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

The recommended v1.92.0+ approach wraps your texture ID before passing it to ImGui functions:

ImTextureRef tex_ref = ImTextureRefFromID(my_tex_id);
ImGui::Image(tex_ref, ImVec2(128, 128));

Working with Font Atlas Textures

The ImFontAtlas stores its texture as an ImTextureRef, illustrating the "internal texture" use case where the texture may be created lazily:

ImFontAtlas* atlas = ImGui::GetIO().Fonts;
ImTextureRef atlas_ref = atlas->TexID;  // Already an ImTextureRef
ImGui::Image(atlas_ref, ImVec2(256, 64));

Backend Implementation

Rendering backends extract the raw ID before binding, as implemented in imgui_draw.cpp:

// Inside draw list processing
ImTextureID texture_id = draw_cmd.TextureRef.GetTexID();
// Bind to graphics pipeline
BindTexture(texture_id);

Summary

  • ImTextureID is defined in imgui.h as typedef ImU64 ImTextureID; and represents a raw 64-bit backend-specific GPU handle.
  • ImTextureRef is a wrapper struct introduced in v1.92.0 containing either an ImTextureID or an ImTextureData* pointer for internal atlas textures.
  • Convert from ID to Ref using ImTextureRefFromID() or direct construction; extract the ID using GetTexID().
  • All user-facing drawing functions now accept ImTextureRef instead of raw ImTextureID values.
  • The change to ImU64 in v1.91.4 ensures 64-bit texture handles work correctly on 32-bit platforms.

Frequently Asked Questions

When should I use ImTextureRef instead of ImTextureID?

Use ImTextureRef for all Dear ImGui API calls such as ImGui::Image() or when storing texture references in your own draw commands. Reserve ImTextureID for backend-specific code that binds actual GPU resources, or when interfacing with rendering APIs directly. The wrapper allows ImGui to handle internal atlas textures that may not have GPU handles yet.

Why was ImTextureID changed from void* to ImU64 in v1.91.4?

The change to ImU64 in v1.91.4 ensures that 64-bit texture identifiers (common in modern graphics APIs like Vulkan with descriptor sets) can be stored correctly even when compiling for 32-bit platforms. A void* on 32-bit systems is only 32 bits, which would truncate 64-bit handles and cause rendering errors.

Can I still pass raw ImTextureID to ImGui functions?

While the underlying ImTextureID type still exists, user-facing functions in v1.92.0+ expect ImTextureRef parameters. However, ImTextureRef provides implicit construction from ImTextureID via the ImTextureRefFromID() helper, allowing legacy code to compile with minimal changes while encouraging the new pattern for new development.

How do I access the texture reference stored in ImDrawCmd?

The ImDrawCmd structure stores texture information as an ImTextureRef member named TextureRef. When implementing a custom renderer, extract the backend-specific handle using cmd.TextureRef.GetTexID() before binding the texture for the draw call, as shown in the reference implementation within imgui_draw.cpp.

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 →