My question is really about low-level rendering techniques, but I’m going to illustrate it with a high-level GUI example. I’m not so much interested in GUI design, but rather in some basic concepts involving coordinate systems and trasformations in a rendering pipeline. I’m sure that this is a well understood problem, but I can’t seem to come up with the right keywords to find the answers I need, so let me try to explain it in simple terms.
Say we have some sort of strategy game, Crusader Kings is a good illustration.
There are essentially three different types of objects that are being rendered:
- World objects: terrain, cities, units, etc. The game keeps track of the world coordinates of these objects. They are submitted to the rendering pipeline which applies all necessary transformations so that they end up in the right place on the screen. As the player zooms in/out or pans around, the view transformation is updated so the map moves as expected.
- "Static" GUI elements: sidebars, topbars, windows, event icons, etc. The positions of these are computed directly in screen coordinates (or possibly some other very close coordinates, in any case unrelated to the world coordinates). As the player moves the map, their position and size remain unchanged.
- "Dynamic" GUI elements: city name banners, army banners etc. These are odd ones out in that their positions depend on world coordinates (as they are attached to specific world objects), but their size in screen coordinates is fixed. As the player pans around, they move along with their coresponding world object. But as the player zooms in/out, their size remains unchanged. (Note that in the screenshot above the county names are written directly "on terrain" and they scale with the map, so they belong to type 1.)
If I was trying to recreate this in OpenGL, I would have a program for rendering the world objects and I would transform them with standard projection-view-model transformations. I would have a separate program for the static GUI elements. But I can’t quite envision a clean way of handling the dynamic GUI elements.
- I could send them through the world-rendering program, but then I would have to manually adjust their size depending on the current view transformation so that their size in screen coordinates remains constant.
- I could send them throuth the GUI-rendering program, but then I have to manually compute their screen coordinates based on world coordinates of the world objects they are attached to (thus duplicating the work already done by the world-rendering program).
Both these feel like ad hoc work arounds. What is a more natural approach?