ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
61.02k stars 10.28k forks source link

Rendering an image without dealing directly with the underlaying textures #4007

Closed Aang23 closed 3 years ago

Aang23 commented 3 years ago

Version/Branch of Dear ImGui:

Version: 1.83 Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_glfw_opengl3.cpp Compiler: GCC 10 Operating System: Linux

My Issue/Question:

First of all, to clear up any doubts, yes I have read the wiki on the topic.

In my usecase (probably unusual), my application is split into several parts :

Currently ImGui is compiled into the core library, without linking to any backend and thus not making the main library dependent on OpenGL, GLFW or anything else when the GUI code is not required. Instead, the UI implementation initializes OpenGL, GLFW and ImGui before calling the code present in the core.

As of now, this has worked flawlessly and I've been extensively using the DrawList for everything custom I required, but yesterday, I ended up with a bit of an issue... I would like to draw a raw image buffer (unsigned short[]) on the UI. I first tried utilizing the ImGui::Image, but since this requires an OpenGL GLuint to be generated, loaded and then passed to this function it does not work in my case. Linking the core to OpenGL really isn't a viable option.

So now, I am wondering : Is there any (perhaps even much less efficient ways) to load an image in ImGui without dealing with OpenGL directly? As of now I've mostly thought about either adding in such a function in ImGui and the GLFW backend, or dealing with the DrawList again (which would be a terrible way to do it in my opinion...).

What do you think would be the best way to approach the issue? Thanks otherwise!

rokups commented 3 years ago

Note that ImGui::Image() takes an opaque pointer. It can be anything you want. What is important is that your banckend understands this pointer value and knows how to handle it. In the end there is absolutely no way you can avoid dealing with uploading texture to GPU through graphics API. It all boils down to how you will abstract it away.

ocornut commented 3 years ago

As answered above there's no magic way out. (other than the EXTREMELY SILLY workaround of submitting every single pixel via ImDrawList rectangles, which is going to kill your performances)

I would like to draw a raw image buffer (unsigned short[]) on the UI. I first tried utilizing the ImGui::Image, but since this requires an OpenGL GLuint to be generated, loaded and then passed to this function it does not work in my case. Linking the core to OpenGL really isn't a viable option.

Your application/engine will need a helper to load a texture and work that out with the active rendering stack (OpenGL, DirectX etc.). For most basic use, it's only a matter of pasting that tutorial code into your own file/library and use that. Wherever you are compiling/linking the imgui_impl_opengl3 backend you can also include some helper to perform that job, I'm not sure I understand what you are suggesting is a problem but you will indeed need some glue to connect that to your app if you want it to be renderer-agnostic. It seems like you have all elements are your disposal to do that.

( Note that we have considered providing higher-level helpers in backends to facilitate creation/management of textures in a way that can be easily be reused across backends, but if you stray away from the most simple case, it can become an unwieldy problem to handle (with low-level api like Vulkan/DX12, tracking resources of in-flight frames still being rendered etc, variety of textures formats) and straying into that territory is likely going to be unnecessarily complex for us and blurring the lines of what backends are (hint: they are not a game engine). Likely instead we would instead add ways to rewire texture bindings so different loading/bindings pipelines - backend one, engine/app one - can cohabit more easily) )