5 ms·
I can't find a clear explanation of "immediate mode" GUI creation (which this library enables) but it appears to be the sort of paradigm that pre-dated object-o
by mellosouls 6y ago
I can't find a clear explanation of "immediate mode" GUI creation (which this library enables) but it appears to be the sort of paradigm that pre-dated object-oriented and event-driven interaction handling that became the norm in the mid 90s (especially after the popularising of dev tools from Borland and Microsoft eg. Visual Basic etc), so I guess it is a formalisation of the procedural (?) methods from the era preceding that.
https://wiki.c2.com/?ImmediateModeGui https://wiki.c2.com/?ImmediateModeGui
- llimllib 6y agoI haven't watched it in a long time, but I recall this as a useful video about it: https://www.youtube.com/watch?v=Z1qyvQsjK5Y https://www.youtube.com/watch?v=Z1qyvQsjK5Y
- ratww 6y agoImmediate Mode GUIs are just GUIs that are instanced and drawn immediately during a single frame. There's no need to persist any object or structure because the whole screen will be cleaned and redrawn in the next frame. Immediate mode is popular in video games because in most games the screen is re-rendered on each frame. This is in opposition from retained-mode, where things are re-rendered only when necessary, like in Win32/Cocoa or the HTML DOM. With those, you need to keep an object in memory. The nature of the job is what allows for very simple procedure calls that looks almost declarative. Here's an example (it's Unity3D btw): GUI.Label (new Rect (25, 25, 100, 30), "Label"); if (GUI.Button (new Rect (25, 25, 100, 30), "Button")) { // This code is executed when the Button is clicked }
- diath 6y ago> Immediate mode is popular in video games because in most games the screen is re-rendered on each frame. That makes no sense though because while you still need to re-render each frame, you do not necessarily have to waste rendering time on GUI each frame when GUIs are mostly static, why not just render the interface to a framebuffer and then simply draw that when composing a frame and only re-draw the framebuffer when the GUI changed/played an animation frame?
- formerly_proven 6y agoI have my hands on a moderately complex ImGUI project right now and the entire thing is basically a few thousand polys in a handful of drawcalls. For a GUI that doesn't cover the entire viewport I'd wager that your approach would actually be slower, because (1) change detection is CPU-side and non-trivial (2) rasterizing and shading this little each frame is probably less expensive than blending with a viewport-sized buffer. In games ImGUI is usually used for debugging purposes and I don't think in that usage you have many frames where nothing would change (e.g. if you are looking at scene-graph nodes their properties will probably constantly change due to things like idle animations, camera movements, scripting, ...)
- gw 6y agoYou can do that if you want. You can also just sleep the render thread until inputs are received, if you are sure that only user input can cause changes in the UI. See glfwWaitEvents for example: https://www.glfw.org/docs/latest/group__window.html#ga554e37d781f0a997656c26b2c56c835e https://www.glfw.org/docs/latest/group__window.html#ga554e37...
- amelius 6y agoBut if it's fast enough for games, why make GUIs unnecessarily complex? Redrawing every frame from scratch is just much simpler than keeping track of differences, invalidating areas (which can go wrong), etc. Perhaps in low-power situations it's a different story, though.
- ratww 6y ago> why not just render the interface to a framebuffer and then simply draw that when composing a frame and only re-draw the framebuffer when the GUI changed/played an animation frame Some games did that in the past, and some might still do it! But keep in mind that today the performance gains are so negligible when compared to the rest of the things you have to render on a single frame that the added complexity and the amount of things that could go wrong (glitches) are normally not worth it. Also, copying that temporary framebuffer to the screen on each frame is not free and involves copying between two memory locations, whereas procedurally drawing things only involves CPU (or GPU) + the main framebuffer, which is super fast in comparison.
- flohofwoe 6y ago> There's no need to persist any object or structure because This isn't quite correct, at least for the library internals. Dear ImGui does persist UI state between frames, the "immediate mode" term only describes how the API looks like to the user, not how the library behind the API is implemented. The user code doesn't need to keep "widget handles" around, and there is no "event handler code" that is called asynchronously. From the user's point of view, control flow is entirely sequential, the UI is described and input events are processed in the same linear control flow context. But this is just what the library user sees, what happens under the hood is very different (e.g. the internal UI state is not rebuilt every frame from scratch, instead the API calls cause changes to the internal UI representation, those API calls just happen to also contain all the information needed to create the required internal UI state if it doesn't exist yet). There's also nothing preventing the library from only redrawing what has changed, it just turned out that redrawing everything is usually so fast that only drawing what has changed would just add complexity to the implementation for very little gain (even complex ImGui UIs are usually a few dozen drawcalls at most and don't take up any significant chunk of the per-frame budget). This description may be simplified and in details also slightly incorrect, but it's important to point out that "immediate mode" only applies to the API, not to the implementation, because this argument is often brought up by critics (who often don't quite understand what the "immediate" in "immediate mode UIs" is actually about) as a reason why immediate mode UIs can never be as efficient as traditional "retained mode" UIs (in reality they usually are more efficient than traditional UIs, and situations where traditional UIs are ahead can be optimized in immediate mode UIs just as well).
- Jasper_ 6y agoCorrect. In order to tell if a button is clicked, you need to know whether it was clicked last frame, which means keeping around state. One difficulty with immediate-style GUIs is that it's difficult to tell whether two widgets are "the same". Dear ImGUI mostly uses a widget's label as its core identifier, which can cause issues if the button label changes. There's actually a lot more in common between React and ImGUI than you might think, in terms of "state reconciliation". The difference is that React is diffing to apply itself to a retained model, while ImGUI retains the state behind your back.
- amelius 6y agoThis library has functions such as add_button() that can be used to create a hierarchy of widgets. From this, I suspect that the library is not fully operating in immediate mode, but perhaps it uses some kind of mixed mode?
- formerly_proven 6y agoThe example only goes through the code once and then enters a GUI loop and also uses callbacks, so ... yeah. Doesn't look like immediate mode GUI to me.
- dragonwriter 6y ago> From this, I suspect that the library is not fully operating in immediate mode, but perhaps it uses some kind of mixed mode? From the linked readme: “DearPyGui provides a wrapping of DearImGui that provides a hybrid of a traditional retained mode GUI and Dear ImGui's immediate mode paradigm.”
- Jhchimaira14 6y agoThe hybrid aspect of it is through using it's data storage system, opening the event loop, clearing widgets every frame, and adding them every frame. We haven't completed the full documentation on using it this way but its there. And because of the IMGUI underneath, using it this way doesn't take any real performance hits.
- smaddox 6y agoAs far as I can piece together, Casey Muratori first described the approach in an early YouTube video in 2005: https://youtu.be/Z1qyvQsjK5Y https://youtu.be/Z1qyvQsjK5Y The basic approach certainly existed far earlier, though. Early "graphical" command line applications, for example, most likely all took an immediate mode approach. It's just that no one thought it was worth making the distinction until after living through the hell that is retained mode GUI programming. In a way, React (along with other vdom-based GUI frameworks) is another rediscovery of immediate mode GUI techniques, but with more of a functional (reactive) programming influence.
- emmanueloga_ 6y agofrom the docs [1]: "A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely." This is cool, I had that misunderstanding myself (immediate mode vs immediate rendering) 1: https://github.com/ocornut/imgui#how-it-works https://github.com/ocornut/imgui#how-it-works
- Renaud 6y agoA 3 minute explanation for the visually inclined: https://www.youtube.com/watch?v=LSRJ1jZq90k https://www.youtube.com/watch?v=LSRJ1jZq90k