Imgui: Custom OpenGL rendering inside an imgui window?

Created on 1 Jun 2018  路  4Comments  路  Source: ocornut/imgui

1.59 / master
slightly modified imgui_impl_glfw / OpenGL / Windows 10

(I'm using Python bindings to imgui, so the impl file is technically different, but it's more or less a direct port.)

Hi! I'm building an app which will heavily use plots generated by an external library, which can render them using OpenGL. I'd like to embed these plots in imgui windows. Here's the approach I came up with:

  • Using the library, render a plot onto a texture/buffer/something
  • Display that image with ImGui:Image

My question is, is this a good way of doing it, or is there a better one? I'd really appreciate any advice/guidance :)

(I'm new to OpenGL, so please excuse any misuse of terms)

drawindrawlist opengl

Most helpful comment

@mgsweet The easy and flexible way is to render to texture (which is something you can figure out on OpenGL side, it's not really an ImGui thing). Once you have a texture you can just call ImGui::Image() with your texture identifier.

If you need to debug your render-to-texture remember you can use GPU Debugger such as RenderDoc to figure out what your render targets contains.

All 4 comments

Hello,

This is a good way of doing it. There's not much more to say than what you wrote, rendering OpenGL into a texture is not a one-line change but it's still fairly easy and well documented on the internet.

Technically, you could skip the intermediary buffer by using ImDrawList callbacks to render your contents directly into the output framebuffer. It's much more error prone (in term of messing with GL state) and less flexible, but you'll save a bit of bandwidth if you are bottle-necked with that. I wouldn't advise starting there unless you know you need to.

Here's the FAQ entry about rendering your texture in imgui:

 Q: How can I display an image? What is ImTextureID, how does it works?
 A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function.
    Dear ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry!
    It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc.
    At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render.
    Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing.

       // The example OpenGL back-end uses integers to identify textures. 
       // You can safely store an integer into a void* by casting it. e.g. (void*)(intptr_t)MY_GL_UINT to cast to void*.
       GLuint my_opengl_texture;
       glGenTextures(1, &my_opengl_texture);
       // [...] load image, render to texture, etc.
       ImGui::Image((void*)(intptr_t)my_opengl_texture, ImVec2(512,512));

       // The example DirectX11 back-end uses ID3D11ShaderResourceView* to identify textures.
       ID3D11ShaderResourceView* my_texture_view;
       device->CreateShaderResourceView(my_texture, &my_shader_resource_view_desc, &my_texture_view);
       ImGui::Image((void*)my_texture_view, ImVec2(512,512));

    To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions.
    Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use.
    You may call ImGui::ShowMetricsWindow() to explore active draw lists and visualize/understand how the draw data is generated.
    It is your responsibility to get textures uploaded to your GPU.

Thanks for the quick reply! Good to know that I'm on the right track. If I run into efficiency problems, I'll look into the alternative you mentioned.

(My question is pretty much answered, so if you like, please close this thread)

As a green hand of opengl and imgui, after some useless coding, I am still confused about how to do some 3D custom rendering inside an imgui window like the game view in Lumix Engine. How can I do this and is there some demos or simple examples that can help?

@mgsweet The easy and flexible way is to render to texture (which is something you can figure out on OpenGL side, it's not really an ImGui thing). Once you have a texture you can just call ImGui::Image() with your texture identifier.

If you need to debug your render-to-texture remember you can use GPU Debugger such as RenderDoc to figure out what your render targets contains.

Was this page helpful?
0 / 5 - 0 ratings