要在渲染管道中使用任何VkImage(包括交换链中的VkImage),我们必须创建一个VkImageView对象。图像视图实际上是图像的视图。它描述了如何访问图像以及要访问图像的哪个部分,例如,如果应该将其视为2D纹理深度纹理而不使用任何mipmapping级别。
在本章中,我们将编写一个createImageViews函数,该函数为交换链中的每个图像创建一个基本图像视图,以便以后可以将它们用作颜色目标。
首先添加一个类成员以存储图像视图:
std::vector<VkImageView> swapChainImageViews;
创建createImageViews函数,并在创建交换链后立即调用它。
void initVulkan() {
createInstance();
setupDebugMessenger();
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];
viewType和format字段指定应如何解释图像数据。viewType参数允许您将图像视为1D纹理、2D纹理、3D纹理和立方体贴图。
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = swapChainImageFormat;
组件字段允许您快速调整颜色通道。例如,可以将所有通道映射到单色纹理的红色通道。还可以将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;
subsourceRange字段描述图像的用途以及应访问图像的哪个部分。我们的图像将用作颜色目标,无需任何mipmapping级别或多层。
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
如果您正在使用立体3D应用程序,那么您将创建具有多个图层的交换链。然后,通过访问不同的图层,可以为每个图像创建多个图像视图,表示左眼和右眼的视图。
创建图像视图现在需要调用vkCreateImageView:
if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!");
}
与图像不同,图像视图是由我们明确创建的,因此我们需要添加一个类似的循环,以在程序结束时再次销毁它们:
void cleanup() {
for (auto imageView : swapChainImageViews) {
vkDestroyImageView(device, imageView, nullptr);
}
...
}
图像视图足以开始将图像用作纹理,但它还没有完全准备好用作渲染目标。这需要另一个间接步骤,称为帧缓冲区。但首先我们必须设置图形管道。