天天看點

Vulkan Tutorial 09 圖像與視圖

作業系統:Windows8.1

顯示卡:Nivida GTX965M

開發工具:Visual Studio 2017

使用任何的VkImage,包括在交換鍊或者渲染管線中的,我們都需要建立VkImageView對象。從字面上了解它就是一個針對圖像的視圖或容器,通過它具體的渲染管線才能夠讀寫渲染資料,換句話說VkImage不能與渲染管線進行互動。除此之外,圖像視圖可以進一步定義具體Image的格式,比如定義為2D貼圖,那麼本質上就不需要任何級别的mipmapping。

在本章節我們會新增一個createImageViews函數,為每一個交換鍊中的圖像建立基本的視圖,這些視圖在後面的内容中會被作為顔色目标與渲染管線配合使用。

首先添加一個類成員用于儲存圖像視圖的句柄集:

std::vector<VkImageView> swapChainImageViews;      

建立createImagesViews函數,并在建立交換鍊完成之後調用:

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];      

其中viewType和format字段用于描述圖像資料該被如何解釋。viewType參數允許将圖像定義為1D textures, 2D textures, 3D textures 和cube maps。

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;      

subresourceRangle 字段用于描述圖像的使用目标是什麼,以及可以被通路的有效區域。我們的圖像将會作為color targets,沒有任何mipmapping levels 或是多層 multiple layers。

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應用程式,比如VR,就需要建立支援多層的交換鍊。并且通過不同的層為每一個圖像建立多個視圖,以滿足不同層的圖像在左右眼渲染時對視圖的需要。

建立圖像視圖調用vkCreateImageView函數:

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

與圖像不同的是,圖像視圖需要明确的建立過程,是以在程式退出的時候,我們需要添加一個循環去銷毀他們。

void cleanup() {    for (size_t i = 0; i < swapChainImageViews.size(); i++) {
        vkDestroyImageView(device, swapChainImageViews[i], nullptr);
    }

    ...
}      

擁有了圖像視圖後,使用圖像作為貼圖已經足夠了,但是它還沒有準備好作為渲染的 target 。它需要更多的間接步驟去準備,其中一個就是 framebuffer,被稱作幀緩沖區。但首先我們要設定圖形管線。