【游戏引擎开发日志2】Vulkan整合Imgui

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

本文的内容是介绍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类中实现。它的工作流程如下:

  1. 初始化vulkan渲染资源,包括创建顶点和索引缓冲、加载shader,创建管线等;
  2. 加载字体相关贴图资源,创建该贴图的描述符集;
  3. 外部提交渲染命令;
  4. 更新缓冲区数据,主要是顶点和索引缓冲数据。如果有必要,需重建顶点和索引缓冲区;
  5. 读取渲染命令,执行vulkan渲染操作;
  6. 返回步骤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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值