Кто еще со мной не знаком, я технический переводчик из ижевской компании CGTribe, и я занимаюсь переводом руководства к Vulkan API (vulkan-tutorial.com).

В этой публикации представлен перевод главы Image view из раздела Drawing a triangle, подраздела Presentation.

Содержание
1. Вступление

2. Краткий обзор

3. Настройка окружения

4. Рисуем треугольник

  1. Подготовка к работе
  2. Отображение на экране
  3. Основы графического конвейера (pipeline)
  4. Отрисовка
  5. Повторное создание цепочки показа

5. Буферы вершин

  1. Описание
  2. Создание буфера вершин
  3. Staging буфер
  4. Буфер индексов

6. Uniform-буферы

  1. Дескриптор layout и буфера
  2. Дескриптор пула и sets

7. Текстурирование

  1. Изображения
  2. Image view и image sampler
  3. Комбинированный image sampler

8. Буфер глубины

9. Загрузка моделей

10. Создание мип-карт

11. Multisampling

FAQ

Политика конфиденциальности


Image views


Для использования VkImage мы должны создать объект VkImageView в графическом конвейере. Image view — это буквально взгляд в image. Он описывает, как интерпретировать image и какая часть image будет использоваться.

В этой главе мы напишем функцию createImageViews, которая создаст базовый image view для каждого image в swap chain, чтобы в дальнейшем использовать их в качестве буфера цвета (color target).

Прежде всего добавим член класса для хранения image views:

std::vector<VkImageView> swapChainImageViews;

Создадим функцию createImageView и вызовем ее сразу после создания swap chain.

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

void createImageViews() {

}

Первое, что мы сделаем — выделим необходимое место в контейнере, чтобы вместить все image views.

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

}

Затем создадим цикл, который обходит все image из swap chain.

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

}

Параметры для создания image view передаются в структуру VkImageViewCreateInfo. Первые несколько параметров не вызывают сложностей.

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

Поля viewType и format указывают, как нужно интерпретировать данные image. Параметр viewType позволяет использовать изображения как 1D, 2D, 3D текстуры или cube maps.

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

Поле components позволяет переключать цветовые каналы между собой. Например, мы можем считывать все цветовые каналы только из r компоненты, получив тем самым монохромную картинку. Или, например, назначить 1 или 0 как константу для альфа канала. Здесь же мы будем использовать дефолтные настройки.

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 описывает, какая часть image будет использоваться. Наши images состоят только из 1 слоя без уровней детализации и будут использоваться в качестве буфера цвета.

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

Если вы работаете со стереоизображениями, вам нужно создать swap chain с несколькими слоями. После чего для каждого image создайте несколько image views с отдельным изображением для каждого глаза.

Для создания image view осталось вызвать функцию vkCreateImageView:

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

В отличие от объектов VkImage, image views были созданы нами, поэтому нужно описать аналогичный цикл, чтобы уничтожить их перед закрытием программы:

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

    ...
}

Нам достаточно image view, чтобы использовать image в качестве текстуры, однако чтобы использовать image в качестве render target, нужно создать фреймбуфер. Но сначала настроим графический конвейер.

C++