2019年11月25日 星期一

運用 Viewport 修正 Vulkan 的Y軸繪圖空間

運用 Viewport 修正 Vulkan 的Y軸繪圖空間 

前言

  最近在學習 Vulkan ,但發現到 Vulkan 的Y軸繪圖空間跟 Direct3D 與 OpenGL 不一樣,幸運地,是有辦法將會Y軸繪圖空間修正回來,在此把學習的過程做個紀錄。

內容

  首先先來了解 Vulkan 的Y軸繪圖空間有何不一樣,如下圖
Y軸繪圖空間的差異

可以在圖中看到 Vulkan 的Y軸繪圖空間是從"下到上",但舊的 API 的Y軸繪圖空間卻是從"下到上",如果是從舊的 API 整合 Vulkan 到繪圖引擎就會發生繪製的結果上下顛倒的問題,信運地,在經過 google 後找到  [ Sascha Willems ] Flipping the Vulkan viewport ,裡面有提到解決的方法。

  解決的方法是透過 Viewport 來修正Y軸的繪圖空間,但要用這個方法時必須開啟"VK_KHR_maintenance1",這是一個 Device extension ,要在 VkDeviceCreateInfo 裡的啟動。在啟動"VK_KHR_maintenance1"後,就可以利用 Viewport  來修正Y軸了,如何修正呢?在 VkViewport::height 裡填上"負"的高度,這樣整個Y軸繪製空間就會變成"下到上",如果沒開啟"VK_KHR_maintenance1"填上負值會在 Debug 訊息回報該值不能是負值。填完"負"的高度得到的結果如下圖
填完"負"的高度的繪製結果

圖中 Render result 的部分是繪製的結果但這次的Y軸是"下到上",藍色的部分是最後會被寫到 Render target 的區域,所以還要將繪製的結果校正到這個區域才能達到目的,如何校正呢?在 VkViewport::y 裡加一個"正"的高度就可以達到目的。最後提供一個轉換的範例如下
void SetUpViewportAndCorrectYAxis(VkViewport& viewport,float x,float y,float width,float height,float minDepth,float maxDepth)
{
  viewport.x = x;
  viewport.y = -y + height;
  viewport.width = width;
  viewport.height = -height;
  viewport.minDepth = mixDepth;
  viewport.maxDepth = maxDepth;
}

參考資料

[ Sascha Willems ] Flipping the Vulkan viewport

沒有留言:

張貼留言