Vulkan 帧缓冲区
Vulkan 帧缓冲区(Framebuffer)是一个容器对象(资源管理类型的对象),包含了一组图像视图(Image Views),用于在渲染通道(Render Pass)中作为附件(Attachments)进行渲染。
每个帧缓冲区的附件与渲染通道的附件描述(Attachment Description)相对应,它们共同定义了渲染的目标,重点强调一下,附件必须与渲染通道的附件描述匹配。
帧缓冲区在 Vulkan 中的概念类似于 OpenGL 的帧缓冲对象(FBO),每个帧缓冲区包含一组图像视图,这些图像视图表示实际的图像资源,可以是颜色附件、深度附件或模板附件,帧缓冲区用于将渲染输出写入这些图像中(存储渲染通道(Render Pass)输出的图像)。
在 Vulkan 中,每个帧缓冲区至少需要一个颜色附件,而这个颜色附件可以是与 SwapChain 关联的 ImageView。
创建 Vulkan 帧缓冲区
帧缓冲区的创建过程通常涉及以下步骤:
- 确定帧缓冲区需要兼容的 RenderPass(前文中已经讲过),因为 RenderPass 定义了渲染操作的结构和执行顺序,以及所需的附件的数量、类型和格式。
- 为每个 SwapChain 图像创建对应的 ImageView (前文中已经讲过),因为最终渲染的图像需要显示在屏幕上,SwapChain 的 ImageView 就是用来呈现到屏幕上的。
- 使用 VkFramebufferCreateInfo 结构体来创建 Framebuffer,指定渲染通道、附件个数、附件信息、宽度、高度和层数等参数。
用于创建帧缓冲区(Framebuffer)的结构体 VkFramebufferCreateInfo :
typedef struct VkFramebufferCreateInfo {
VkStructureType sType; // 必须是 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
const void* pNext; // 指向扩展结构的指针,通常为 nullptr
VkFramebufferCreateFlags flags; // 帧缓冲区创建标志,目前保留,必须为 0
VkRenderPass renderPass; // 与帧缓冲区相关联的渲染通道(Render Pass)
uint32_t attachmentCount; // 帧缓冲区的附件数量
const VkImageView* pAttachments; // 指向 VkImageView 的指针数组,每个指针指向一个附件
uint32_t width; // 帧缓冲区的宽度
uint32_t height; // 帧缓冲区的高度
uint32_t layers; // 帧缓冲区的层数(通常为 1)
} VkFramebufferCreateInfo;
创建包含颜色、深度模版附件的帧缓冲区:
1 // 创建交换链图像视图(作为颜色附件)
2 std::vector<VkImageView> swapChainImageViews(swapChainImages.size());
3 for (size_t i = 0; i < swapChainImages.size(); i++) {
4 VkImageViewCreateInfo createInfo = {};
5 createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
6 createInfo.image = swapChainImages[i]; // 交换链图像
7 createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; // 2D 图像视图
8 createInfo.format = swapChainImageFormat; // 图像格式
9 createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; // 红色分量
10 createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; // 绿色分量
11 createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; // 蓝色分量
12 createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; // 透明度分量
13 createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // 颜色附件
14 createInfo.subresourceRange.baseMipLevel = 0; // 基础 mip 级别
15 createInfo.subresourceRange.levelCount = 1; // mip 级别数量
16 createInfo.subresourceRange.baseArrayLayer = 0; // 基础数组层
17 createInfo.subresourceRange.layerCount = 1; // 数组层数量
18
19 if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
20 throw std::runtime_error("failed to create image views!");
21 }
22}
23
24 //创建深度模版图像视图
25 VkImage depthStencilImage;//假设已经创建好
26 VkImageView depthStencilImageView;
27 VkImageViewCreateInfo viewInfo = {};
28 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
29 viewInfo.image = depthStencilImage;
30 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
31 viewInfo.format = depthFormat;
32 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
33 viewInfo.subresourceRange.baseMipLevel = 0;
34 viewInfo.subresourceRange.levelCount = 1;
35 viewInfo.subresourceRange.baseArrayLayer = 0;
36 viewInfo.subresourceRange.layerCount = 1;
37
38 if (vkCreateImageView(device, &viewInfo, nullptr, &depthStencilImageView) != VK_SUCCESS) {
39 throw std::runtime_error("failed to create depth image view!");
40}
41
42
43 // 创建帧缓冲区
44 std::vector<VkFramebuffer> swapChainFramebuffers(swapChainImageViews.size());
45 for (size_t i = 0; i < swapChainImageViews.size(); i++) {
46 std::array<VkImageView, 2> attachments = {
47 swapChainImageViews[i], // 颜色附件
48 depthStencilImageView // 深度模板附件
49 };
50
51 VkFramebufferCreateInfo framebufferInfo = {};
52 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
53 framebufferInfo.renderPass = renderPass; // 前文创建好的渲染通道
54 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size()); // 附件数量
55 framebufferInfo.pAttachments = attachments.data(); // 附件数组数据
56 framebufferInfo.width = swapChainExtent.width; // 帧缓冲区宽度
57 framebufferInfo.height = swapChainExtent.height; // 帧缓冲区高度
58 framebufferInfo.layers = 1; // 层数量
59
60 if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
61 throw std::runtime_error("failed to create framebuffer!");
62 }
63}
64
65 // Vulkan 编程。。。
66
67 // 销毁帧缓冲区
68 for (size_t i = 0; i < swapChainFramebuffers.size(); i++) {
69 vkDestroyFramebuffer(device, swapChainFramebuffers[i], nullptr);
70}
71
72 // 销毁交换链图像视图
73 for (size_t i = 0; i < swapChainImageViews.size(); i++) {
74 vkDestroyImageView(device, swapChainImageViews[i], nullptr);
75 }
76
77 // 销毁深度模板图像视图
78 vkDestroyImageView(device, depthStencilImageView, nullptr);
进技术交流群,扫码添加我的微信:Byte-Flow
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/51736.html