Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
C++ Game Animation Programming

You're reading from   C++ Game Animation Programming Learn modern animation techniques from theory to implementation using C++, OpenGL, and Vulkan

Arrow left icon
Product type Paperback
Published in Dec 2023
Publisher Packt
ISBN-13 9781803246529
Length 480 pages
Edition 2nd Edition
Languages
Tools
Concepts
Arrow right icon
Authors (2):
Arrow left icon
Michael Dunsky Michael Dunsky
Author Profile Icon Michael Dunsky
Michael Dunsky
Gabor Szauer Gabor Szauer
Author Profile Icon Gabor Szauer
Gabor Szauer
Arrow right icon
View More author details
Toc

Table of Contents (22) Chapters Close

Preface 1. Part 1:Building a Graphics Renderer
2. Chapter 1: Creating the Game Window FREE CHAPTER 3. Chapter 2: Building an OpenGL 4 Renderer 4. Chapter 3: Building a Vulkan Renderer 5. Chapter 4: Working with Shaders 6. Chapter 5: Adding Dear ImGui to Show Valuable Information 7. Part 2: Mathematics Roundup
8. Chapter 6: Understanding Vector and Matrix 9. Chapter 7: A Primer on Quaternions and Splines 10. Part 3: Working with Models and Animations
11. Chapter 8: Loading Models in the glTF Format 12. Chapter 9: The Model Skeleton and Skin 13. Chapter 10: About Poses, Frames, and Clips 14. Chapter 11: Blending between Animations 15. Part 4: Advancing Your Code to the Next Level
16. Chapter 12: Cleaning Up the User Interface 17. Chapter 13: Implementing Inverse Kinematics 18. Chapter 14: Creating Instanced Crowds 19. Chapter 15: Measuring Performance and Optimizing the Code 20. Index 21. Other Books You May Enjoy

Using helper libraries for Vulkan

Having full control of your graphics hardware sounds cool, but the extensive amount of code for the basic initialization might scare people who are new to Vulkan. Writing about 1,000 lines of code just to get a colored triangle onto the screen may sound frightening.

To reduce the code a bit, two helper libraries are integrated:

  • vk-bootstrap, the Vulkan Bootstrap, which is for the first steps of creating the instance, device, and swapchain
  • The Vulkan Memory Allocator (VMA), taking some of the complexity out of the memory management out of the code

We start with the simplification of the creation of the most important objects.

Initializing Vulkan via vk-bootstrap

If you visit the GitHub page for vk-bootstrap at https://github.com/charles-lunarg/vk-bootstrap, the benefits are listed right at the top of the README file. It will help you with all the steps needed for the following:

  • Instance creation, enabling the validation layers, if desired
  • Selection of the physical device (also with additional criteria)
  • Device and swapchain creation, plus queue retrieving

Next, we will see how to use vk-bootstrap.

You need to download and include three files in your project:

  • VkBootstrap.h
  • VkBootstrapDispatch.h
  • VkBootstrap.cpp

Only the first header file has to be in the files with functions and objects of vk-bootstrap:

#include <VkBootstrap.h>

After this line, you are ready to go. The example code in the Basic Usage section of the vk-bootstrap GitHub page shows the steps to create a Vulkan instance:

vkb::InstanceBuilder builder;
auto inst_ret =
  builder.set_app_name ("Example Vulkan Application")
    .request_validation_layers ()
    .use_default_debug_messenger ()
    .build ();

Here vkb::InstanceBuilder simplifies the creation of the Vulkan instance object. The application name is set first, here just to an example string. The graphics driver could use the name to apply optimizations or bug fixes. The instance will have the validation layers enabled, helping to find incorrect resource usage. The default debug messenger is used by the validation layers, printing out any errors to the command window or the console of the program. With the build() call in the last step, the instance is finally created.

If the Vulkan instance creation fails, we signal this failure to the calling function. And if the creation succeeds, we read the instance value from the builder:

if (!inst_ret) {
  std::cerr << "Failed to create Vulkan instance" << "\n";
  std::cerr << "Error: " << inst_ret.error().message() <<
    "\n";
  return false;
}
vkb::Instance vkb_inst = inst_ret.value();

The vk-bootstrap objects reside in the C++ namespace called vkb. Also, a lot of functions are attached to these objects; this makes the function calls for all important initialization steps available directly on the vk-bootstrap objects.

You may check the code in the Vulkan tutorial (see the Additional resources section) and compare the amount of code required to create a Vulkan instance with the validation layers enabled at https://github.com/Overv/VulkanTutorial/blob/main/code/02_validation_layers.cpp.

The preceding vk-bootstrap code takes less than 15 lines of code; the full-featured Vulkan code of the tutorial is about 200 lines long. And that’s just the instance creation; you also need to select the physical device, the logical device, and the queues.

As we need to acquire and free the memory for every Vulkan image and buffer, we use the Vulkan Memory Allocator (VMA). VMA was created by Advanced Micro Devices (AMD), and the source code is freely available as Open Source library. Working with VMA makes our lives a bit easier compared to using only the built-in Vulkan functions.

Memory management with VMA

The memory management of Vulkan images and buffers lies entirely in the hands of the programmers.

OpenGL hides the process of the creation and deletion of textures behind a single line. You just have to point it to the source image loaded into the memory of your computer. But Vulkan forces you to allocate and free the memory, in addition to the definition of all resources for the image. This includes finding the right memory type for the image you want to create, calculating the correct size, and binding the acquired memory to the buffer. Even with some helper code to detect the memory types, you will be far away from the simplicity of VMA.

To use VMA, download the vk_mem_alloc.h file from the GitHub project page (see the Additional resources section), put it into the include path of your project, and include it:

#include <vk_mem_alloc.h>

After initializing the allocator, you only need a structure and a single call:

VmaAllocationCreateInfo vmaAllocInfo{};
vmaAllocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
vmaCreateBuffer(allocator, &bufferInfoStruct,
  &vmaAllocInfo, &mVertexBuffer, &mVertexBufferAlloc,
  nullptr);

All remaining calculations of the size, memory type, and binding are hidden behind this one call.

After all the theoretical parts of the Vulkan API, let’s take a closer look at some implementation details, including more about vk-bootstrap and VMA.

lock icon The rest of the chapter is locked
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.
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 $19.99/month. Cancel anytime