mirror of
https://github.com/ocornut/imgui.git
synced 2026-11-06 06:25:54 +01:00
Use casting to ImTextureID instead of void*
parent
6830bb9389
commit
e51b260a8c
@ -72,12 +72,12 @@ From the FAQ: "How can I display an image? What is ImTextureID, how does it work
|
||||
|
||||
Short explanation:
|
||||
- You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures. Using `ImGui::GetBackgroundDrawList()` you may submit AddImage() calls that are not part of a specific ImGui window but displayed between your background contents and ImGui windows.
|
||||
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as a `ImTextureID` value (which is no other than a `void*`).
|
||||
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as a `ImTextureID` value (which is no other than an opaque u64/void* type).
|
||||
- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason). You can read documentations or tutorials on your graphics API to understand how to upload textures. Onward in this document you'll find examples.
|
||||
|
||||
Long explanation:
|
||||
- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
|
||||
- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API. We carry the information to identify a "texture" in the ImTextureID type. ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice. Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
|
||||
- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API. We carry the information to identify a "texture" in the ImTextureID type. ImTextureID default to ImU64, aka 8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice (note: before 1.91.3, ImTextureID defaulted to being a void*, which couldn't fit e.g. a 64-bit descriptor in 32-bits builds). Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
|
||||
- In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using:
|
||||
```
|
||||
OpenGL: ImTextureID = GLuint (see ImGui_ImplOpenGL3_RenderDrawData() in imgui_impl_opengl3.cpp)
|
||||
@ -91,14 +91,14 @@ For example, in the OpenGL example binding we store raw OpenGL texture identifie
|
||||
- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them. If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID representation suggested by the example bindings is probably the best choice. (Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
|
||||
User code may do:
|
||||
```cpp
|
||||
// Cast our texture type to ImTextureID / void*
|
||||
// Cast our texture type to ImTextureID
|
||||
MyTexture* texture = g_CoffeeTableTexture;
|
||||
ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
|
||||
ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2(texture->Width, texture->Height));
|
||||
```
|
||||
The renderer function called after ImGui::Render() will receive that same value that the user code passed:
|
||||
```cpp
|
||||
// Cast ImTextureID / void* stored in the draw command as our texture type
|
||||
MyTexture* texture = (MyTexture*)pcmd->TextureId;
|
||||
// Cast ImTextureID stored in the draw command as our texture type
|
||||
MyTexture* texture = (MyTexture*)(intptr_t)pcmd->TextureId;
|
||||
MyEngineBindTexture2D(texture);
|
||||
```
|
||||
Once you understand this design you can begin understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them. In reality, the concept of what constitute a "texture" is largely open-ended, and Dear ImGui doesn't want to narrow that concept. If you want to display an image file (e.g. PNG file) into the screen, please refer to tutorials above.
|
||||
@ -185,7 +185,7 @@ Now that we have an OpenGL texture and its dimensions, we can display it in our
|
||||
ImGui::Begin("OpenGL Texture Text");
|
||||
ImGui::Text("pointer = %x", my_image_texture);
|
||||
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
|
||||
ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_image_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::End();
|
||||
```
|
||||
|
||||
@ -237,7 +237,7 @@ Now that we have an DirectX9 texture and its dimensions, we can display it in ou
|
||||
ImGui::Begin("DirectX9 Texture Test");
|
||||
ImGui::Text("pointer = %p", my_texture);
|
||||
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
|
||||
ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::End();
|
||||
```
|
||||
|
||||
@ -335,7 +335,7 @@ Now that we have an DirectX11 texture and its dimensions, we can display it in o
|
||||
ImGui::Begin("DirectX11 Texture Test");
|
||||
ImGui::Text("pointer = %p", my_texture);
|
||||
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
|
||||
ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::End();
|
||||
```
|
||||
|
||||
@ -646,7 +646,7 @@ And finally, use the image with Dear ImGui:
|
||||
ImGui::Begin("SDL2/SDL_Renderer Texture Test");
|
||||
ImGui::Text("pointer = %p", my_texture);
|
||||
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
|
||||
ImGui::Image((void*) my_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2(my_image_width, my_image_height));
|
||||
ImGui::End();
|
||||
```
|
||||
|
||||
@ -1083,9 +1083,9 @@ For the purpose of this section we use "Texture Coordinates" and "UV Coordinates
|
||||
The `ImGui::Image()` and `ImDrawList::AddImage()` functions allow you to pass "UV coordinates" corresponding to the upper-left and bottom-right portion of the texture you want to display. Using the default values, respectively `(0.0f, 0.0f)` and `(1.0f, 1.0f)` for those coordinates allow you to display the entire underlying texture. UV coordinates are traditionally normalized coordinates, meaning that for each axis, instead of counting a number of texels, we address a location in the texture using a number from 0.0f to 1.0f. So (0.0f, 0.0f) is generally addressing the upper-left section of the texture and (1.0f, 1.0f) is addressing the lower-right corner of the texture. Some graphics systems may use coordinates that are inverted on the Y axis.
|
||||
|
||||
```cpp
|
||||
ImGui::Image((void*)my_texture, ImVec2(256, 256), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); // Default coordinates
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2(256, 256), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); // Default coordinates
|
||||
ImGui::Text("Flip Y coordinates:");
|
||||
ImGui::Image((void*)my_texture, ImVec2(256, 256), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); // Flip Y coordinates
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2(256, 256), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); // Flip Y coordinates
|
||||
```
|
||||

|
||||
|
||||
@ -1102,7 +1102,7 @@ ImGui::Text("uv0 = (%f, %f)", uv0.x, uv0.y);
|
||||
ImGui::Text("uv1 = (%f, %f)", uv1.x, uv1.y);
|
||||
|
||||
// Display the 100x200 section starting at (10,10)
|
||||
ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(100.0f, 200.0f), uv0, uv1);
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_image_texture, ImVec2(100.0f, 200.0f), uv0, uv1);
|
||||
```
|
||||
|
||||
Same code written differently, with named variables:
|
||||
@ -1122,7 +1122,7 @@ ImGui::Text("uv0 = (%f, %f)", uv0.x, uv0.y);
|
||||
ImGui::Text("uv1 = (%f, %f)", uv1.x, uv1.y);
|
||||
|
||||
// Display the 100x200 section starting at (10,10)
|
||||
ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(display_size.x, display_size.y), uv0, uv1);
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_image_texture, ImVec2(display_size.x, display_size.y), uv0, uv1);
|
||||
```
|
||||
|
||||

|
||||
@ -1134,10 +1134,10 @@ If you want to display the same image but scaled, keep the same UV coordinates b
|
||||
|
||||
```cpp
|
||||
// Normal size
|
||||
ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(my_image_width, my_image_height), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_image_texture, ImVec2(my_image_width, my_image_height), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
|
||||
|
||||
// Half size, same contents
|
||||
ImGui::Image((void*)(intptr_t)my_image_texture, ImVec2(my_image_width*0.5f, my_image_height*0.5f), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_image_texture, ImVec2(my_image_width*0.5f, my_image_height*0.5f), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
|
||||
```
|
||||
|
||||

|
||||
@ -1179,7 +1179,7 @@ void ImDrawCallback_ImplDX11_SetSampler(const ImDrawList* parent_list, const ImD
|
||||
```cpp
|
||||
// Usage
|
||||
ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ImplDX11_SetSampler, g_SamplerPoint); // Set custom sampler
|
||||
ImGui::Image((void*)my_texture, ImVec2((float)my_image_width * 4, (float)my_image_height * 4));
|
||||
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2((float)my_image_width * 4, (float)my_image_height * 4));
|
||||
ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ImplDX11_SetSampler, NULL); // Restore sampler
|
||||
```
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user