Debug Gizmos (part 1)

PlatwoPlatwo
5 min read

Debugging gizmos are not the most glamorous things, but they can be vital to the creation, and proper working, of numerous in-game and engine systems. To fully explain what I mean by debug gizmos, here is a screenshot from an old Unity project which shows spheres and lines depicting bounding areas around parts of a character:

The green objects are there purely for debugging purposes, to add visualization of existing information, and to make modifying that data easier - such as changing the scale of a bounding sphere.

Uses for Gizmos

There are a large number of uses for gizmos - practically anything that has data and represents something could have a gizmo to visually represent that thing in the world. Here is a short list of potential uses:

  • Bounding boxes

  • Frustum view volumes

  • Normals of surfaces

  • Quad-trees breakdown

  • Moving/scaling/rotating object in the world

  • World space grid lines

  • Character view directions

  • World probes

  • Mathematical representations (planes, collision points, ect)

  • AI decision making information

Each one requires different gizmos to be used in different ways, and in different combinations, which makes it vital for the underlying gizmo system to be as flexible as possible.

Different Inherent Types

To add useful data visualizations, there are a bunch of different types of gizmos that can be rendered. The key ones that come to mind are:

  • Points

  • Lines

  • Cubes

  • Spheres

  • Planes

Multiple of these may need to be combined together to achieve the final effect, for example in the previous unity screenshot there were both spheres and cubes depicting bounding areas. Here is an example in-engine image showing debug points placed at the corners of a cube:

Creating Different Types of Gizmos

When implementing the concept of gizmos into my engine, there were a lot of different considerations to solve. The first, and most important, one was how is it going to fit into the render flow that underpins my whole frame creation system. (As these gizmos need to be engine only and not be part of any game compilation)

How this was solved was through using the trusty #ifdef pre-processor definitions. So, first I added a new render frame segment type to represent the gizmo rendering:

enum class RenderedFrameSegmentType : unsigned int
{
    IMAGE_AVALIABLE = 0,
    OPAQUE_UI_RENDER = 1,

    // If opaque meshes on screen //
    OPAQUE_MODELS_RENDER = 2,
    AO_GENERATION = 3,
    DEFERRED_BUFFERS_COLLATED = 4,

    ...

    POST_PROCESSING = 12,

#ifdef _ENGINE_BUILD
    DEBUG_GIZMOS = 13,
    IMGUI_RENDER = 14,
#endif

    COUNT
};

What this does is, in any build of the engine, these frame segments will exist and be run. But for any release version of the game, they will be stripped out.

If you wanted to add the same idea into your visual studio project, here is a quick rundown of how:

  • First you want to choose your flags - in my case it was engine build, and game build.

  • Go into configuration manager

  • From within configuration manager you can add new configurations for different compilations you want to do

  • After creating your configuration name, go to the properties of your project (at the bottom of here)

  • Then go to Configuration Properties → C/C++ → Preprocessor → Preprocessor definitions:

  • In the pre-processor definitions section you can add your flags

  • You will need to do this for each project that you are using, as they do not carry over.

  • And now if you swap to that configuration and type something like:

  •       #ifdef YOUR_FLAG_NAME
    
          #else
    
          #endif
    
  • Then the code in the first block will be highlighted like normal, and anything in the second part will be grayed out and not compiled.

  • Now back to gizmos :D

Debug Camera Only

Another consideration was if the gizmos would only show on the debug camera, or all cameras. The only answer that made sense to me at this point was to only have them show on the debug camera - as the game cameras are meant to be ‘in’ the world. So they can’t ‘see‘ anything that is debug only.

This did prompt another interesting question though - do the gizmos need to respect any depth buffer or should they render over the top of everything? This is a tricky question and one that I have not got an answer for as of yet. Currently my engine has them rendering over the top of everything else, but if it starts to look strange then I will look into trying other approaches.

Different Vertex Data Typologies

One final important consideration for rendering gizmos is what topology they should be using. For anyone unfamiliar with the term, topology refers to how primitives within a vertex buffer are laid out with respect to them being clustered together during rendering. For clarity, here are the options within Vulkan:

typedef enum VkPrimitiveTopology {
    VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
    VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1,
    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2,
    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3,
    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4,
    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5,
    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6,
    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7,
    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8,
    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9,
    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10,
    VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF
} VkPrimitiveTopology;

Where VK_PRIMITIVE_TOPOLOGY_POINT_LIST, for example, says that the vertex buffer contains a list of single points in space. Whereas VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST instead states that they are clustered into groups of three, each cluster defining a full triangle.

Why this is important is because if I want to render a group of points in space I am going to need to use VK_PRIMITIVE_TOPOLOGY_POINT_LIST instead of other typologies. And, as the topology is baked into a graphics pipeline, that means the program is going to need a different graphics pipeline per gizmo type. Implementing this is not particularly difficult, just potentially tedious.

Conclusion

To conclude, this blog post has aimed to cover what debug gizmos are, and some of the behind the scenes implementation details that go into creating them within an engine.

The next blog post is going to be a large expansion to this one. It is going to add more detail on implementing debug lines, planes, spheres, and cubes. And how to hook into this system from external systems.

Thanks for reading :D

0
Subscribe to my newsletter

Read articles from Platwo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Platwo
Platwo

Professional games programmer from England, who has a first class degree, and has worked in the industry at both AAA and smaller indie levels. And who's next endeavour is to make my own custom game engine and game, which my blogs will be covering in detail.