[Vulkan教程]绘制一个三角形/呈现/图像视图(Image views)

要在渲染管线中使用任何VkImage,包括交换链中的,我们必须创建一个VkImageView对象。图像视图就如同其字面意思,图像的视图(额~)。他描述了如何访问图像以及要访问图像的哪个部分。例如,把一个图像视为2D深度纹理,没有任何MIPMAP。

本章,我们会编写一个createImageViews函数,该函数为交换链中的每一个图像创建一个基本的图像视图,以便我们稍后可以将它们作为颜色目标。

首先添加一个类成员来保存图像视图:

  1. std::vector<VkImageView> swapChainImageViews;
  2. 1

创建createImageViews函数并在创建交换链后立即调用它。

  1. void initVulkan() {
  2. createInstance();
  3. setupDebugMessenger();
  4. createSurface();
  5. pickPhysicalDevice();
  6. createLogicalDevice();
  7. createSwapChain();
  8. createImageViews();
  9. }
  10. void createImageViews() {
  11. }
  12. 12345678910111213

我们要做的第一件事是调整列表的大小以适合我们将要创建的所有图像视图:

  1. swapChainImageViews.resize(swapChainImages.size());
  2. 1

然后,创建循环迭代所有交换链图像。

  1. for (size_t i = 0; i < swapChainImages.size(); i++) {
  2. }
  3. 123

创建图像视图的参数在VkImageViewCreateInfo中指定。前几个参数很简单。

  1. VkImageViewCreateInfo createInfo{};
  2. createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  3. createInfo.image = swapChainImages[i];
  4. 123

viewTypeformat字段指定如何解释图像数据。viewType允许你将图像视为1D纹理、2D纹理、3D纹理或立方纹理。

  1. createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  2. createInfo.format = swapChainImageFormat;
  3. 12

components成员允许你调整颜色通道。例如,你可以将所有通道映射到单色纹理的红色通道,你也可以将01的常量值映射到通道。在我们的程序中,我们使用默认映射。

  1. createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  2. createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  3. createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  4. createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  5. 1234

subresourceRange字段描述了图像的用途以及应该访问图像的哪个部分。我们的图像会用作颜色目标,并且是单层的、没有任何mipmap级别的。

  1. createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  2. createInfo.subresourceRange.baseMipLevel = 0;
  3. createInfo.subresourceRange.levelCount = 1;
  4. createInfo.subresourceRange.baseArrayLayer = 0;
  5. createInfo.subresourceRange.layerCount = 1;
  6. 12345

如果你正在搞VR程序,那你会创建一个多层的交换链。然后通过不同的层的图像,为左眼和右眼创建多个图像视图。(TODO HOW)

现在只需要调用vkCreateImageView即可创建图像视图:

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

和图像不同,图像视图由我们显式创建,因此我们需要添加一个类似的循环,在程序结束时销毁它们:

  1. void cleanup() {
  2. for (auto imageView : swapChainImageViews) {
  3. vkDestroyImageView(device, imageView, nullptr);
  4. }
  5. ...
  6. }
  7. 1234567

图像视图足以使图像作为纹理来使用,但它还不能作为渲染目标。中间还差个帧缓冲区。但首先我们需要设置图形管线。