# Difference Between ImTextureID and ImTextureRef in Dear ImGui

> Understand the difference between ImTextureID and ImTextureRef in Dear ImGui. Learn how ImTextureRef enhances texture handling for your GPU applications.

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

---

**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`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/imgui.h), it is defined as:

```cpp
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`](https://github.com/ocornut/imgui/blob/main/imgui.h), the structure contains two key members:

- `_TexData`: A pointer to `ImTextureData` for internal atlas textures
- `_TexID`: The low-level `ImTextureID` for 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`](https://github.com/ocornut/imgui/blob/main/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:

```cpp
// 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:

```cpp
// 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:

```cpp
// 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:

```cpp
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`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/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 from `void*` in v1.91.4 to support 64-bit identifiers on 32-bit platforms.
- **ImTextureRef** is a wrapper struct introduced in v1.92.0 containing `_TexData` and `_TexID` members, enabling ImGui to reference both user textures and internal atlas data.
- Convert from `ImTextureID` to `ImTextureRef` using `ImTextureRefFromID()`, and extract the raw ID via `GetTexID()` when binding textures in your backend.
- `ImDrawCmd` stores `ImTextureRef` to support deferred texture resolution and dynamic atlas updates.
- All new code should use `ImTextureRef` for 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`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/imgui.h), or construct an `ImTextureRef` directly by passing your ID to the constructor:

```cpp
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`](https://github.com/ocornut/imgui/blob/main/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.