图像视图
前言
要使用任何 vk::Image
,都必须先创建一个 vk::ImageView
对象。
ImageView 从字面上看就是图像的视图。 它描述了如何访问图像以及访问图像的哪一部分,例如它是否应该被视为没有 mipmap 深度级别的 2D 纹理图像。
在本章中,我们将为交换链中的每个图像创建一个图像视图,以便稍后将它们用作渲染目标。
创建图像视图
1. 添加基本结构
首先添加一个类成员来存储图像视图。注意图像视图需要手动回收资源,所以我们使用 RAII 封装。
std::vector<vk::raii::ImageView> m_swapChainImageViews;
创建 createImageViews
函数并在交换链创建后立即调用它。
void initVulkan() {
createInstance();
setupDebugMessenger();
createSurface();
selectPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
}
void createImageViews() {
}
2. 批量创建图像视图
设置循环以迭代所有交换链图像,图像视图需要一个一个创建。
m_swapChainImageViews.reserve( m_swapChainImages.size() );
for (const auto& image : m_swapChainImages) {
// ......
}
注意
resize
是不行的,因为不支持无参构造。需要使用reserve
仅分配空间而不实例化内容。
图像视图创建的参数在 vk::ImageViewCreateInfo
结构中指定,前几个参数很简单:
vk::ImageViewCreateInfo createInfo;
createInfo.image = image;
createInfo.viewType = vk::ImageViewType::e2D;
createInfo.format = m_swapChainImageFormat;
-
viewType
参数允许您将图像视为 1D、2D、3D 和立方体贴图。 -
components
字段我们未设置(默认),它允许您调换颜色通道。例如,您可以将所有通道映射到红色通道以获得单色纹理。
下面设置 subresourceRange
字段,它描述了图像的用途以及应访问图像的哪一部分。
createInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
第一个字段指定图像存放的数据类型,我们存放的是“色彩”数据。 此外还有“深度”和“模板”,我们会在“深度缓冲”章节介绍。
我们的图像将用在没有 mipmap
级别和多层颜色的目标上。
注意没有额外 mip
级别和层次,但是原图自身占一个级别和层次,所以 levelCount
和 layerCount
为 1
。
如果您正在开发立体的 3D 应用程序,那么您将创建一个具有多层的交换链。 然后,您可以为每个图像创建多个图像视图,通过访问不同的图层来表示左眼和右眼的视图。
现在,创建图像视图:
m_swapChainImageViews.emplace_back( m_device.createImageView(createInfo) );
测试
现在运行程序保证没有异常。
图像视图足以将图像用作纹理,但它还不能完全用作渲染目标。 正如“教程前言”部分所述,我们需要将图像视图(作为附件)绑定到帧缓冲中,并在渲染过程中添加对应的附件描述。