操作系統: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,被稱作幀緩沖區。但首先我們要設置圖形管線。
項目代碼 GitHub 獲取。