Skip to content

HUD Spaces

Zach Hembree edited this page Jan 29, 2021 · 11 revisions

Every UI element in the framework is drawn using textured quads located in the game's world-space, each element associated with a HUD Space Node. These nodes, in turn, define 2D planes embedded in world-space that their children will are rendered to using their Plane-To-World (PTW) matrix transforms.

By default, UI elements will use the Pixel-To-World transform supplied by HudMain, and as the name suggests, that transform is used to draw elements in screen space, with units in pixels and the origin at the center of the screen. Technically, nothing rendered by this framework draws in screen-space, but for the sake of brevity and clarity, that's the terminology I'll be sticking with.

If you're not interested in drawing UI elements in world space or creating your own draw matrices, then you can stop here. If you're uncomfortable with matrix transforms or any of the other concepts discussed here, then you might want to do a little extra research. Personally, I think LearnOpenGL is a great resource for this kind of stuff.

HUD Space Nodes:

Each of these nodes are responsible not only for updating their PTW matrices but for calculating the position of the cursor over their planes as well as their distances from the screen at that point. This allows UI elements attached to that node to determine when they're moused over and whether or not they're occluded by other elements at that point, allowing the cursor to function regardless of the local coordinate system of that node. By default, this is handled automatically in HudSpaceNodeBase using the inverse PTW matrix.

At the time of writing this, there are two types of HUD Space Node: CustomSpaceNode and CamSpaceNode. CustomSpaceNode is the most open-ended and allows you to update the PTW matrix using a delegate. CamSpaceNode, on the other hand, is more specialized and is designed to allow you to more easily create custom screen spaces by allowing you to specify custom scaling, rotation, and offset with respect to the camera.

You can try out the CamSpaceNode in real-time in the Rich HUD Terminal by enabling debugging with the "/rhd toggleDebug" chat command and opening the Demo page.

Depth Sorting:

As mentioned previously, UI elements in this framework are rendered using textured quads, semitransparent textured quads, to be specific. I mention this because of the way 3D renderers handle semitransparent geometry. Where opaque geometry occludes, semitransparent fragments have to be blended with the fragments behind them and in the correct order. Otherwise, you'd end up with semitransparent objects that draw on top of objects that should be in front of them and all sorts of unpleasant artifacts.

Typically, this is accomplished by sorting per-object s.t. semitransparent objects furthest are drawn first and those closest are drawn last, but in this framework, it's done per HUD Space, with the origin/translation of that space being used to calculate distance from the camera.