DevLog 01 - Adding a Camera and ImGui
- Bobbie Kindt

- Aug 29
- 2 min read
Updated: Sep 14
Introduction
With the base renderer in place, the next step was making the project easier to use and debug. For this, I focused on two features:
A simple camera system, so I could finally move around the scene instead of staring at a rotating mesh
ImGui integration, to give me an immediate way to visualize information and build debugging tools
Both turned out very differently in terms of difficulty while the camera was very straightforward, getting ImGui to play nicely with Vulkan took a lot of trial and error.
What I Did
Camera
For the camera, I used the GLM library to handle matrices and transformations. My camera class keeps track of position, orientation, and movement input. It updates a view matrix every frame and responds to both keyboard and mouse input. This part was relatively smooth since GLM is designed with graphics in mind and integrates naturally with Vulkan’s math requirements.
glm::mat4 Camera::Update()
{
return glm::lookAt(m_CameraPosition, m_CameraPosition + m_CameraForward, m_CameraUp);
}This let me fly around the scene and explore from different angles. A small change, but it instantly made testing easier and the overall scene more engaging.
ImGui
ImGui was a whole different beast. There aren’t many clear or up-to-date resources for integrating ImGui with Vulkan. Most guides I found were either outdated or missing important steps. I noticed a lot of example code used depricated functions and later figured out that these function calls were now being done in the background by ImGui itself like ImGui_ImplVulkan_CreateFontsTexture. After a lot of trial and error, I pieced together a working approach:
Creating a dedicated descriptor pool for ImGui.
Initializing the ImGui context and setting up GLFW + Vulkan bindings.
Hooking into my existing render pass to make sure ImGui could render on top of my scene.
// 2. Setup ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
// 3. Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForVulkan(m_pWindow->GetWindow(), true);
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = m_pVulkanInstance->GetInstance();
init_info.PhysicalDevice = m_pVulkanDevice->GetPhysicalDevice();
init_info.Device = m_pVulkanDevice->GetDevice();
init_info.QueueFamily = m_pVulkanDevice->FindQueueFamilies(m_pVulkanDevice->GetPhysicalDevice()).graphicsFamily.value();
init_info.Queue = m_pVulkanDevice->GetGraphicsQueue();
init_info.PipelineCache = VK_NULL_HANDLE;
init_info.DescriptorPool = imguiPool;
init_info.Subpass = 0;
init_info.MinImageCount = utils::MAX_FRAMES_IN_FLIGHT;
init_info.ImageCount = utils::MAX_FRAMES_IN_FLIGHT;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = nullptr;
init_info.RenderPass = m_pVulkanRenderPass->GetRenderPass();
ImGui_ImplVulkan_Init(&init_info);Once it was running, I started simple: a debug window showing frame rate. From there, it’s easy to expand into more tools and overlays.

Challenges & Fixes
The camera wasn’t particularly challenging, GLM did most of the heavy lifting. ImGui, however, took the most time. The lack of consistent documentation meant I had to combine information from several sources and adapt it to modern Vulkan practices. Eventually, I built a structured initialization flow for ImGui in my project, so now adding UI elements is straightforward.
What's Next
Now that I have a camera and a debug UI, I can start tackling deferred rendering. This is a big step, it means enabling Vulkan’s Synchronization2 and dynamic rendering, which will move my project closer to a modern rendering pipeline.


Comments