Reader small image

You're reading from  C++ Game Animation Programming - Second Edition

Product typeBook
Published inDec 2023
Reading LevelN/a
PublisherPackt
ISBN-139781803246529
Edition2nd Edition
Languages
Tools
Concepts
Right arrow
Authors (2):
Michael Dunsky
Michael Dunsky
author image
Michael Dunsky

Michael Dunsky is an educated electronics technician, game developer, and console porting programmer with more than 20 years of programming experience. He started at the age of 14 with BASIC, adding on his way Assembly language, C, C++, Java, Python, VHDL, OpenGL, GLSL, and Vulkan to his portfolio. During his career, he also gained extensive knowledge in virtual machines, server operation, infrastructure automation, and other DevOps topics. Michael holds a Master of Science degree in Computer Science from the FernUniversität in Hagen, focused on computer graphics, parallel programming and software systems.
Read more about Michael Dunsky

Gabor Szauer
Gabor Szauer
author image
Gabor Szauer

Gabor Szauer has been making games since 2010. He graduated from Full Sail University in 2010 with a bachelor's degree in game development. Gabor maintains an active Twitter presence, and maintains a programming-oriented game development blog. Gabor's previously published books are Game Physics Programming Cookbook and Lua Quick Start Guide, both published by Packt.
Read more about Gabor Szauer

View More author details
Right arrow

5

Adding Dear ImGui to Show Valuable Information

Welcome to Chapter 5! In the previous chapter, we took a close look at shaders, small programs running on the GPU that do the main work in the process of creating stunning 3D worlds on your screen. In this chapter, we will go from the internals of the drawing process to the visual side and create a user interface for both renderers.

Displaying 3D objects without any additional information is nice for a purely graphical demonstration, but an application should also give the user some kind of data about the objects visible on the screen. In addition, the application could display details about its internal state, such as the amount of resources used. On the other hand, the manipulation of object properties should also be possible without having to remember dozens of key combinations. UI elements such as buttons, sliders, or color selectors simplify the process of changing model data, enabling easy-to-use workflows, even for inexperienced...

Technical requirements

For this chapter, you will need the OpenGL and/or Vulkan renderer code from Chapter 4.

What is Dear ImGui?

Dear ImGui, or ImGui for short, is a graphical user interface library for C++, using the pipelines of modern 3D APIs to render texts and elements in framebuffers. In addition, ImGui is self-contained, which means we do not need additional dependencies besides GLFW, OpenGL, and Vulkan. It is also platform-independent, so the application code still runs on both Windows and Linux.

To get a first impression, here is a screenshot of some of the elements of ImGui:

Figure 5.1: Some widgets of the Dear ImGui demo code

Figure 5.1: Some widgets of the Dear ImGui demo code

The ImGui code consists of three parts:

  • The widget rendering
  • The input backend
  • The output backend

ImGui aims to create an identical look and feel across all supported operating systems, helper libraries, and rendering backends. To draw the widgets independently of the underlying system, the widget rendering functions are separated from the backends.

The function calls we use are only at the widget...

Adding ImGui to the OpenGL and Vulkan renderers

To use ImGui in our code, we need a couple of files from the ImGui GitHub repository at https://github.com/ocornut/imgui

Download the following files to a folder named imgui:

  • imconfig.h
  • imgui.cpp
  • imgui.h
  • imgui_draw.cpp
  • imgui_internal.h
  • imgui_tables.cpp
  • imgui_widgets.cpp
  • imstb_rectpack.h
  • imstb_textedit.h
  • imstb_truetype.h

These downloaded files are the backend-independent code, containing the implementations of the widgets. We have to include them in our project for ImGui to work in general.

For the GLFW input backend, two additional files are required. Download these two files and put them into the imgui folder:

  • imgui_impl_glfw.cpp
  • imgui_impl_glfw.h

To include the GLFW backend, this line will be needed:

#include <imgui_impl_glfw.h>

You can find the code for this section in the chapter05 folder’s 01_opengl_ui subfolder for OpenGL and 05_vulkan_ui...

Creating an FPS counter

To measure the time it takes to draw a frame, we need a stable time source. Luckily, GLFW has a function we could use for our virtual stopwatch: glfwGetTime(). This function returns the number of seconds since GLFW was initialized as a double type. The resolution of the returned value is system-dependent, but GLFW should use the time with the highest resolution. We should get the time down to micro- or nanoseconds.

We start by using GLFW as a simple timer.

Using GLFW as a simple timer

To measure the time the renderer needs to draw the objects to the screen, we save the time given by glfwGetTime() at the start of the draw() method. To be able to calculate the full frame time, including the code in the Window class, we also store the starting time of the previous draw in a static variable. Then, we use a new variable in the OGLRenderData struct to transfer the difference of both time values to the UserInterface class. This difference is simply converted...

Timing sections of your code and showing the results

Our new Timer class uses the C++ chrono library, a specialized part of C++ dealing with clocks, durations, and points in time.

You can find the example code of this section in the 03_opengl_ui_timer and 07_vulkan_ui_timer folders.

Adding the Timer class

Create the new Timer class by adding the Timer.h file in the tools folder:

#pragma once
#include <chrono>

After the header guard, we include the chrono header. The elements from the chrono header can be found in the std::chrono namespace.

Next, add the Timer class itself in the Timer.h file:

class Timer {
  public:
    void start();
    float stop();
  private:
    bool mRunning = false;
    std::chrono::time_point<std::chrono::steady_clock>
      mStartTime{};
};

The Timer class has two public methods: the start() method...

Adding UI elements to control the application

Having values such as the FPS counter of the timers shown in the ImGui window is nice, but ImGui is also capable of sending input to the application. This sending of input enables us to add control elements to the ImGui window and change the values of our running program, without the need to recompile or remember key mappings.

The example code for this last section is in the 04_opengl_ui_control and 08_vulkan_ui_control folders.

To see the generic principle of input controls in ImGui, let’s create a simple example: a checkbox that toggles a Boolean value.

Adding a checkbox

Create the checkbox widget in the UserInterface class by adding these lines to the createFrame() method of the UserInterface.cpp file between the ImGui window position text output widget and the ImGui::End() call:

  static bool checkBoxChecked = false;
  ImGui::Checkbox("Check Me", &checkBoxChecked);
  ...

Summary

In this chapter, you learned how to add ImGui to the application to create a simple, widget-based UI, enabling you to output valuable data from your application, such as the FPS counter and various timings of code passages and functions. You also learned how to use ImGui widgets as input elements to control your application using a mouse.

A large variety of ImGui widgets is available already in the official GitHub repository, and many more have been created and contributed by users around the world. So, if you need a widget for some kind of UI task, there’s a chance such a widget is already available and waiting to be used.

In the next chapter, we take a closer look at vector and matrix data types and the operations between them using GLM. Having the operations at hand, without the need to define them for all data types, makes our lives much easier. We will peek into the mathematical background of some operations to understand what happens in the code and in the...

Practical sessions

Here are some additional suggestions to implement after you have finished reading:

  • Adjust the ImGui window properties by using the window flags to disable properties such as the collapsing of the window, or the movement of it, and watch the result. You can find all supported flags in the imgui.h file.
  • Change the checkbox to enable or disable vertical sync. This may be a bit tricky, as the UserInterface class may have no direct access to all the data you need. One idea to achieve this VSync change is toggling a Boolean variable in the OGLRenderData struct as a flag when the checkbox has been clicked and handling the change of this flag in the draw() method of the renderer.
  • Add additional output to the ImGui window, such as the contents of the perspective and view matrix. You have to move them to the OGLRenderData / VkRenderData struct to access them from the UserInterface class. GLM has a glm::to_string() function, which works like std::to_string(...

Additional resources

lock icon
The rest of the chapter is locked
You have been reading a chapter from
C++ Game Animation Programming - Second Edition
Published in: Dec 2023Publisher: PacktISBN-13: 9781803246529
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at AU $19.99/month. Cancel anytime

Authors (2)

author image
Michael Dunsky

Michael Dunsky is an educated electronics technician, game developer, and console porting programmer with more than 20 years of programming experience. He started at the age of 14 with BASIC, adding on his way Assembly language, C, C++, Java, Python, VHDL, OpenGL, GLSL, and Vulkan to his portfolio. During his career, he also gained extensive knowledge in virtual machines, server operation, infrastructure automation, and other DevOps topics. Michael holds a Master of Science degree in Computer Science from the FernUniversität in Hagen, focused on computer graphics, parallel programming and software systems.
Read more about Michael Dunsky

author image
Gabor Szauer

Gabor Szauer has been making games since 2010. He graduated from Full Sail University in 2010 with a bachelor's degree in game development. Gabor maintains an active Twitter presence, and maintains a programming-oriented game development blog. Gabor's previously published books are Game Physics Programming Cookbook and Lua Quick Start Guide, both published by Packt.
Read more about Gabor Szauer