跳到主要内容

图像视图

在渲染管线中使用VkImage对象(包括交换链中的图像),都必须创建一个绑定到图像的VkImageView才能访问它。图像视图描述了访问图像的方式,以及图像的哪一部分可以被访问,比如,可以描述为一个没有mipmapping 的二维深度纹理,进而可以对其进行二维深度纹理相关的操作。

我们添加createImageViews函数来为交换链中的每一个图像建立图像视图。

首先,添加用于存储图像视图的类成员变量:

std::vector<VkImageView> swapChainImageViews;

然后,添加createImageViews函数,并在initVulkan中调用它:

void initVulkan() {
createInstance();
setupDebugCallback();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
}

void createImageViews() {

}

接着,我们分配足够的数组空间来存储图像视图:

void createImageViews() {
swapChainImageViews.resize(swapChainImages.size());

}

遍历所有交换链图像,创建图像视图:

for (size_t i = 0; i < swapChainImages.size(); i++) {

}

我们需要填写VkImageViewCreateInfo结构体来创建图像视图:

VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = swapChainImages[i];

viewTypeformat字段用于指定图像数据的解析方式。

viewType用于指定图像是一维纹理、二维纹理、三维纹理还是立方体贴图。

createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = swapChainImageFormat;

components用于映射图像颜色通道。比如,对于单色纹理,我们可以将所有通道映射到红色。也可以直接将颜色通道映射为常数0或1。这里我们使用默认值:

createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;

subresourceRange用于描述图像的用途和哪一部分可以被访问。在这里,图像被用作渲染目标,并且没有细分级别,只有一个图层:

createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;

如果读者在编写VR一类的应用,可能会使用支持多个层级的交换链。这时读者应该为每个图像都创建多个图像视图,分别对应左眼和右眼两个不同的图层。

调用vkCreateImageView创建图像视图:

if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!");
}

和交换链图像不同,图像视图是由我们自己显式创建的,需要我们自己在cleanup函数中清除:

void cleanup() {
for (auto imageView : swapChainImageViews) {
vkDestroyImageView(device, imageView, nullptr);
}

...
}

有了图像视图,就可以将图像作为纹理使用,但作为渲染目标,还需要帧缓冲对象。接下来的章节,我们会简要介绍渲染管线,然后介绍帧缓冲对象。

本章节代码:C++代码