# How to Use ImTextureID with Custom Texture Types in DirectX

> Learn how to use ImTextureID with custom texture types in DirectX. Redefine ImTextureID in imconfig.h for type safety and eliminate manual pointer casts. Improve your DirectX rendering.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-16

---

**ImTextureID is an opaque graphics handle that you can redefine in [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) to match your DirectX shader resource view type, eliminating manual pointer casts and enabling compile-time type safety.**

Dear ImGui (ocornut/imgui) renders images by storing a lightweight `ImTextureID` inside draw commands. The meaning of this value is determined solely by your renderer backend; for DirectX 11, the backend expects an `ID3D11ShaderResourceView*` pointer. You can either cast this pointer to the default 64-bit integer type or override the type definition itself to embed custom metadata and avoid dangerous reinterpretation.

---

## What Is ImTextureID and How DirectX Interprets It

`ImTextureID` is a typedef that defaults to `ImU64` (64-bit unsigned integer) as of recent versions. In [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), the declaration appears around line 339, accompanied by instructions on how to override it:

```cpp
// imgui.h (lines 339-344)
#ifndef ImTextureID
typedef ImU64 ImTextureID;    // Default: store any 64-bit value (pointer, handle, etc.)
#endif

```

When the DirectX 11 backend processes draw commands in [`backends/imgui_impl_dx11.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_dx11.cpp), it extracts the raw value and casts it directly back to `ID3D11ShaderResourceView*`:

```cpp
// backends/imgui_impl_dx11.cpp (lines 73-158)
ID3D11ShaderResourceView* tex_srv = (ID3D11ShaderResourceView*)cmd->GetTexID();

```

This means **any value you store in `ImTextureID` must be safe to cast to a shader resource view pointer** (or whatever type your specific backend expects) when the render function executes.

---

## Why Define a Custom Type for DirectX Textures

Redefining `ImTextureID` via [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) provides three concrete advantages:

*   **Type Safety:** The compiler catches attempts to pass incompatible pointers (e.g., raw `ID3D11Texture2D*` instead of `ID3D11ShaderResourceView*`).
*   **Zero-Cost Abstraction:** You avoid repetitive `(ImTextureID)(intptr_t)` casts throughout your UI code.
*   **Extended Metadata:** You can store a pointer to a custom struct containing the view plus dimensions, format flags, or engine-specific handles.

---

## Three Implementation Strategies

Choose the approach that matches your team's safety requirements and DirectX workflow.

### Method 1: Direct Casting with Default ImU64 (Legacy Compatible)

Keep the default definition and cast your DirectX resource view to `ImTextureID` using an intermediate `intptr_t` conversion. This works immediately without modifying library headers.

```cpp
ID3D11ShaderResourceView* srv = CreateMyTexture(width, height);
ImTextureID tid = (ImTextureID)(intptr_t)srv;  // Safe intptr_t bridge
ImGui::Image(tid, ImVec2((float)width, (float)height));

```

**Downside:** You lose compiler type checking and must ensure the pointer remains valid for the entire frame.

### Method 2: Redefine ImTextureID as DirectX Pointer (Recommended)

Before including [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), define `ImTextureID` to be exactly `ID3D11ShaderResourceView*`. The canonical location for this is [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) in your project root or alongside your ImGui source:

```cpp
// imconfig.h
#define ImTextureID ID3D11ShaderResourceView*

// Must include imconfig.h before imgui.h (naturally happens if you follow integration guides)
#include "imgui.h"

```

Now you can pass the view directly:

```cpp
ID3D11ShaderResourceView* srv = CreateMyTexture(256, 256);
ImGui::Image(srv, ImVec2(256.0f, 256.0f));  // No cast needed

```

The DirectX 11 backend retrieves the pointer verbatim in [`imgui_impl_dx11.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_dx11.cpp) (line 73 ff.) and binds it to the pixel shader without additional indirection.

### Method 3: Custom Struct Wrapper (Advanced)

When you need to bundle extra data (size, mip levels, debug names), create a wrapper struct and redefine the type accordingly:

```cpp
// imconfig.h
struct MyDXTexture {
    ID3D11ShaderResourceView* srv;
    int width;
    int height;
    const char* debug_name;
};
#define ImTextureID MyDXTexture*

```

Usage requires dereferencing to access the view, but the backend must be taught how to extract the raw pointer. Since the official backend expects `ID3D11ShaderResourceView*` directly, you have two options:

1.  **Store the view pointer as the ID** and keep your metadata in a parallel lookup table keyed by that pointer.
2.  **Modify the backend** (or wrap it) to perform `tex_id->srv` when binding.

For most applications, storing the raw view pointer as `ImTextureID` and using a separate map for metadata keeps changes minimal and preserves compatibility with [`imgui_impl_dx11.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_dx11.cpp).

---

## DirectX Backend Integration Details

The DirectX 11 renderer never inspects the content of `ImTextureID` until draw submission. In [`imgui_impl_dx11.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_dx11.cpp) (around line 158), the engine iterates over `ImDrawCmd` structures and calls:

```cpp
// Extract the texture pointer stored by ImGui::Image()
ID3D11ShaderResourceView* srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
ctx->PSSetShaderResources(0, 1, &srv);

```

Consequently, **whatever you pass to `ImGui::Image()` must be exactly `sizeof(void*)` or `sizeof(ImU64)` and must be valid when `RenderDrawData()` executes**. If you defined `ImTextureID` as a custom struct pointer, ensure your custom backend extraction matches this definition.

Conversion utilities exist for debugging purposes in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) (function `DebugTextureIDToU64` around line 16580), which handles the cast safely for internal logging.

---

## Practical Code Examples

### Basic DirectX 11 Texture Display

```cpp
// Initialize ImGui with DX11 backend
ImGui_ImplDX11_Init(device, device_context);

// Load texture via D3DX or custom loader
ID3D11ShaderResourceView* my_srv = LoadTextureFromFile("image.png");

// In your render loop
ImGui::Begin("DirectX Texture");
ImTextureID tex_id = (ImTextureID)(intptr_t)my_srv;  // Method 1
ImGui::Image(tex_id, ImVec2(256, 256));
ImGui::End();

```

### Type-Safe Custom Definition

```cpp
// imconfig.h (include before imgui.h)
#define ImTextureID ID3D11ShaderResourceView*

// Application code
void ShowTexture(ID3D11ShaderResourceView* srv, float w, float h) {
    ImGui::Image(srv, ImVec2(w, h));  // Method 2: no cast, type-checked
}

```

### Using ImTextureRef (v1.92+)

The newer `ImTextureRef` API wraps `ImTextureID` with additional safety:

```cpp
// Convert raw view to texture reference
ImTextureRef tex_ref = ImTextureRefFromID((ImTextureID)(intptr_t)srv);
ImGui::Image(tex_ref, ImVec2(128, 128));

```

Refer to [`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) (around line 1888) for expanded examples demonstrating `ImageButton` with explicit string IDs to avoid widget ID collisions.

---

## Summary

-   `ImTextureID` defaults to `ImU64` in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) but can be overridden in [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) to any pointer-sized type.
-   The DirectX 11 backend expects `ID3D11ShaderResourceView*` and casts the ID blindly in [`imgui_impl_dx11.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_dx11.cpp).
-   **Method 1:** Cast via `(ImTextureID)(intptr_t)ptr` for quick integration.
-   **Method 2:** `#define ImTextureID ID3D11ShaderResourceView*` in [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) for type safety.
-   **Method 3:** Wrap custom structs only if you modify the backend extraction logic or maintain a parallel lookup.
-   Keep texture resources alive for the duration of the frame where they are referenced in draw commands.

---

## Frequently Asked Questions

### Can I use ImTextureID with DirectX 12?

**Yes**, but you must adapt the backend. DirectX 12 does not use `ID3D11ShaderResourceView*`; instead you typically pass a `D3D12_GPU_DESCRIPTOR_HANDLE` (which is 64-bit) or a custom index into your descriptor heap. Define `ImTextureID` as `ImU64` (the default) or as your custom handle type, then update [`imgui_impl_dx12.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_dx12.cpp) to interpret the value correctly when calling `SetGraphicsRootDescriptorTable`.

### Why did ImTextureID change from void* to ImU64 in recent versions?

Prior to v1.91.4, `ImTextureID` was defined as `void*`. The change to `ImU64` (as seen in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) lines 339-344) prevents accidental pointer arithmetic and accommodates graphics APIs that use non-pointer handles (e.g., Vulkan `uint64_t` image views). When porting existing DirectX 11 code, replace `(ImTextureID)ptr` with `(ImTextureID)(intptr_t)ptr` to silence compiler warnings.

### How do I handle multiple texture types in the same application?

If your engine uses different representations for textures (e.g., raw `ID3D11Resource*` vs. wrapped engine handles), **do not** redefine `ImTextureID` to a specific class pointer. Instead, keep the default `ImU64` and store a unified handle (such as a pointer to a base texture struct) that the backend can dispatch on. Alternatively, use separate `ImGuiContext` instances with different backend implementations, though this is rarely necessary.

### What is the difference between ImTextureID and ImTextureRef?

`ImTextureID` is the legacy low-level storage (64-bit integer). `ImTextureRef` (defined around line 350 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)) is a newer wrapper structure that can hold either an `ImTextureID` or a pointer to `ImTextureData` (used for the font atlas). It provides a type-safe way to distinguish between raw GPU handles and CPU-side image data. Use `ImTextureRefFromID()` to construct a reference when migrating code to the newer API introduced in v1.92.