std::vector<vk::raii::ImageView> swapChainImageViews;
要在渲染管线中使用任何 vk::Image(包括交换链中的图像),我们必须创建一个 vk::raii::ImageView 对象。图像视图字面意思就是图像的一个视图。它描述了如何访问图像以及访问图像的哪个部分,例如,是否应将其视为没有任何 mipmap 级别的 2D 纹理深度纹理。
在本章中,我们将编写一个 createImageViews 函数,为交换链中的每个图像创建一个基本的图像视图,以便稍后将它们用作颜色目标。
首先,添加一个类成员来存储图像视图:
std::vector<vk::raii::ImageView> swapChainImageViews;
创建 createImageViews 函数,并在交换链创建之后立即调用它。
void initVulkan()
{
createInstance();
setupDebugMessenger();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
}
void createImageViews()
{
}
图像视图创建的参数在 vk::ImageViewCreateInfo 结构体中指定。对于每个图像视图,viewType、format 和 subresourceRange 都是相同的。
通过 viewType,我们指定要渲染到 2D 屏幕。如果我们想要渲染到 3D 屏幕或立方体贴图,这些也是选项,1D 屏幕也是。你可能已经猜到,在大多数情况下,当我们渲染到屏幕时,我们希望使用 2D 渲染目标。
接下来,我们指定图像格式;这决定了颜色空间分量的配置方式,以便在渲染中获得正确的颜色格式。
接下来,components 字段对于我们的交换链来说不是必需的;但我们稍后会讨论它。
最后一个成员是 subresourceRange,它是必需的,我们稍后会讨论。
void createImageViews()
{
assert(swapChainImageViews.empty());
vk::ImageViewCreateInfo imageViewCreateInfo{ .viewType = vk::ImageViewType::e2D,
.format = swapChainSurfaceFormat.format,
.subresourceRange = { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } };
}
components 字段允许你重新排列颜色通道。例如,你可以将所有通道映射到红色通道以创建单色纹理。你也可以将常量值 0 和 1 映射到某个通道。在我们的例子中,我们将使用默认映射(接受构造的默认值),但下面是如何显式设置的方法:
imageViewCreateInfo.components = {
vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity};
subresourceRange 字段描述图像的用途以及应访问图像的哪个部分。我们的图像将用作颜色目标,没有任何 mipmap 级别或多层。
注意:你可以像上面代码片段那样列出 subresourceRange 的所有元素,或者使用指定初始化器仅初始化那些与默认值不同的成员,如下所示:
imageViewCreateInfo.subresourceRange = {.aspectMask = vk::ImageAspectFlagBits::eColor, .levelCount = 1, .layerCount = 1};
如果你正在开发立体 3D 应用程序,那么你将创建一个包含多个层的交换链。然后,你可以为每个图像创建多个图像视图,通过访问不同的层来表示左右眼的视图。
你应该期望显卡能够处理的最大多个图像视图数量是 16。这种配置涵盖了大多数标准用例,VR/AR 头显通常需要的并发视图不超过四个。然而,光场显示器和 CAVE 显示器可能需要不同的解决方案,因为它们对并发视图的需求可能数以千计。这些特殊的渲染需求超出了本教程的范围,但即使是这些用例,也可以使用我们在此描述的相同结构和技术进行渲染。
接下来,设置循环遍历所有交换链图像,并将它们添加到我们的结构体中。
for (auto &image : swapChainImages)
{
imageViewCreateInfo.image = image;
}
创建图像视图现在只需使用 vk::raii::CreateImageView 的构造函数,这里通过 std::vector::emplace_back 来实现:
for (auto &image : swapChainImages)
{
imageViewCreateInfo.image = image;
swapChainImageViews.emplace_back( device, imageViewCreateInfo );
}
图像视图足以开始将图像用作纹理,但它还不能用作渲染目标。这还需要一步,称为帧缓冲。在接下来的章节中,我们将必须设置图形管线。
Vulkan 是 Khronos Group Inc. 的注册商标
教程内容版权归原作者,遵循 CC BY-SA 4.0;本站独立代码及设计除外。