本文的内容是介绍Vulkan整合Imgui的方法。Imgui官方给出了一个整合vulkan的案例,用户可以直接使用该后端进行渲染,也可以自己写vulkan后端进行渲染。本文采取了自己写vulkan后端的方式。若想采用imgui官方的后端,可以把imgui_impl_vulkan.h/cpp文件包含到自己的工程中使用。
初始化
在程序的最开始,程序判断使用哪种api渲染。如果是vulkan渲染,就创建一个VulkanImguiRenderer实例。VulkanImguiRenderer类是我自定义的vullkan imgui渲染类,采用了单例的实现思路,可以直接用类名调用方法。
if (RendererAPI::GetAPI() == RendererAPI::API::OpenGL)
{
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 410");
}
else if (RendererAPI::GetAPI() == RendererAPI::API::Vulkan)
{
ImGui_ImplGlfw_InitForVulkan(window, true);
VulkanImguiRenderer::Create();
}
渲染开始
imgui渲染的方式是:先生成若干绘制命令,再把这些命令统一提交给后端的渲染器,让它执行。开始记录绘制命令需要调用ImGui::NewFrame()函数。记录结束后,使用ImGui::Render()方法提交命令。
if (RendererAPI::GetAPI() == RendererAPI::API::OpenGL)
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGuizmo::BeginFrame();
}
else if (RendererAPI::GetAPI() == RendererAPI::API::Vulkan)
{
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGuizmo::BeginFrame();//坐标轴绘制工具
}
Vulkan后端工作流程
本项目的Imgui渲染后端在VulkanImguiRenderer类中实现。它的工作流程如下:
- 初始化vulkan渲染资源,包括创建顶点和索引缓冲、加载shader,创建管线等;
- 加载字体相关贴图资源,创建该贴图的描述符集;
- 外部提交渲染命令;
- 更新缓冲区数据,主要是顶点和索引缓冲数据。如果有必要,需重建顶点和索引缓冲区;
- 读取渲染命令,执行vulkan渲染操作;
- 返回步骤3循环,直到程序结束。
初始化vulkan资源
首先,创建imgui渲染管线的描述符集布局。这个布局是和imgui的shader对应的,即在0号binding位上有一个VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER类型的资源。
setLayout = std::make_shared<VulkanDescriptorSetLayout>();
setLayout->AddBinding(0, DescriptorType::IMAGE);
setLayout->Build();
同时,Push Constant也是和imgui的shader一一对应的,格式如下:
struct PushConstBlock {
glm::vec2 scale;
glm::vec2 translate;
} pushConstBlock;
接下来,进行渲染管线的配置。配置部分可以参考imgui官方提供的案例和SaschaWillems的vulkan整合imgui案例。
configInfo.inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
configInfo.inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
configInfo.inputAssemblyInfo.flags = 0;
configInfo.inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
configInfo.viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
configInfo.viewportInfo.viewportCount = 1;
configInfo.viewportInfo.scissorCount = 1;
configInfo.viewportInfo.flags = 0;
configInfo.rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
configInfo.rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL;
configInfo.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
configInfo.rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
configInfo.rasterizationInfo.flags = 0;
configInfo.rasterizationInfo.depthClampEnable = VK_FALSE;
configInfo.rasterizationInfo.lineWidth = 1.0f;
configInfo.multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
configInfo.multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
configInfo.multisampleInfo.flags = 0;
// Enable blending
configInfo.colorBlendAttachment.blendEnable = VK_TRUE;
configInfo.colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
configInfo.colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
configInfo.colorBlendAttachment

本文介绍了如何在Vulkan环境中整合Imgui,通过自定义VulkanImguiRenderer实现渲染,涉及资源初始化、缓冲区管理、描述符集绑定和命令提交等关键步骤。
最低0.47元/天 解锁文章
805

被折叠的 条评论
为什么被折叠?



