利用頂點位移進行VR畸變校訂

    VR開發的最大挑戰之一是對高幀率與高分辨率結合的要求。咱們經過把頂點轉化爲「鏡頭空間」,刪除了須要全屏渲染的紋理,這樣就能夠大規模提升手機性能。程序員

下面的技術使用谷歌的Cardboard Unity SDK進行開發,應用於Cardboard Design Lab(CDL),然而,利用透鏡畸變效果,給與適當的失真係數去構成頂點着色器,而且SDK容許禁止渲染紋理,這樣一樣的方法能夠適用於任何VR系統。算法

Google公司的Cardboard Design Lab,在Google Play這個場景中可能使用了惟美的處理,但其實是很是細化。編輯器

一些背景


在審查這個技術以前,重要的是要了解大多數的VR渲染是如何處理的。對於爲何咱們須要鏡頭畸變,以及典型實施的來歷,能夠查看Oculus rift documentation這一部分。函數

鏡頭畸變

VR應用的鏡頭畸變阻礙了頭戴式顯示器(HMDs)的玻璃透鏡的物理畸變,從而獲得一個無明顯失真圖像的寬視野。性能

在大多數VR軟件中,反畸變是經過將每一個照相機渲染成一個單獨的渲染目標來執行,而後將後處理效果的圖像進行扭曲。不管是在一個像素着色器,或者經過將渲染目標投影到一個扭曲的網格上,都將最終輸出渲染到屏幕上。測試

本文演示了一種技術,在場景中的每一個對象都在頂點着色以前執行渲染,從而消除對單獨渲染目標的需求。渲染目標的消除同時幾乎消除掉移動設備上的熱問題,並容許在全分辨率上MSAA增長2至4倍也不會對散熱或目標幀率有顯着影響。優化

值得注意的是,我不是第一個想到這一點的人,但據我所知,Cardboard Design Lab是第一個使用這種技術開發VR應用的。此外在項目開始的時候,谷歌的團隊已經作了頂點變形版本的雛形,最終成爲代碼是包含在今天的SDK。this

因此充分證實,我會由於堅持頂點變形爲基礎的鏡頭校訂可以在生產應用中工做而受到你們的好評,它對於在谷歌已經寫CGine文件的一些性能算法工程師是一種喜訊。我寫這篇文件是由於(A)它確實能使用,(B)但願更多的開發者使用它使VR應用變得更好;(C)引擎開發者實現正向渲染仍然很棒,MSAA仍然很可怕,依靠全屏後處理對核心功能有不良影響。操作系統

問題

在開發一個移動VR應用中,有3個主要的考慮因素影響工程成果,這些因素或多或少約束着什麼是可能的。設計

  1. 幀率
  2. 可視化分辨率
  3. 散熱

幀率

幀率是咱們比較熟悉的。在整場遊戲中30-60幀是廣泛能夠接受的。在VR中,60幀是一個最低限度,並且你們有共識是一個好的VR體驗幀率要在90-120幀之間。

固然,在移動設備上,咱們能夠作得最好。許多設備設置最大幀率是60幀,因此我使用60做爲本文的其他部分的參照。

當一個VR體驗低於60幀,效果是立竿見影的。頭部跟蹤不出現'保持'的顯示時,用戶會迷失方向,而且體驗更可能出現模擬器問題。瞬時性能問題(如背景資料加載、操做系統的通知和垃圾回收)引發短暫但極度的不適,而持續的低幀率(30~60)隨着時間的推移可能有不適的表現。許多用戶沒法自主肯定一個體驗是運行在45幀仍是60幀;然而,在咱們對低幀率的測試中,用戶因爲各類各樣的除了幀率的特徵更可能感到噁心。對於這個緣由,在我看來,VR體驗在30幀是危害極大的,低於30幀是毫無心義的。

 

將一個可視化的幀時間整合顯示到測試版本對於調試是必不可少的。只要確保調試自己沒有以這樣的方式實現,從而致使GC分配或沒必要要的開銷就能夠。上圖:幀率顯示使用環形緩衝區和調用原GL的單繪製。在Unity中頂點調用不要使用GUI系統!

不幸的是,目前不多有可用的移動VR應用程序能夠始終在60幀運行,而且桌面應用程序有嚴格的硬件要求。這些反作用致使VR的最佳作法過於保守。我看過很多文章說「VR用戶的移動老是很差,而運動的某些類型如向視圖方向的運動是有問題,設計良好的60幀跑步運動能夠給絕大多數用戶帶來愉悅感。因爲過山車的普及,VR應用程序能夠足夠被證實,運動是值得研究的。

關鍵點:低於60幀率可讓一個很好的體驗變的使人做嘔,甚至體驗用戶和開發者可能沒法正確識別緣由。

可視化分辨率

可視化分辨率是指如何讓一個場景細節「可視」。在VR,這是一個物理屏幕分辨率、渲染緩衝區的分辨率、MSAA水平、物理鏡頭放大和各類後期處理效果(如透鏡畸變)的組合。

咱們須要多少分辨率?我讀過不少不一樣的數字,但我對事物使用Michael Abrash近似,如每隻眼4K×4K(90度視野)與當前的顯示器相配,和16K×16K(180度視野)與視網膜分辨率相配。

顯然,沒有移動設備是能夠作到,可是若是忽略一些,仍然有作到的。三星Galaxy S6推出每隻眼2560×1440像素或1280×1440像素。在邊緣進行一些損失計算,這大約是1024×1024或1K(是4K的16分之一)。

如今我敢確定,Michael Abrash給的那些數字就是意味着4K×4K的MSAA打開,產生一個糟糕的16K可視分辨率,但原理是相同的,MSAA會幫助你。

關鍵點:抗混疊是很是重要的,即便昂貴。我喜歡在高端手機追求4x的MSAA。打破你的正向渲染吧。

簡而言之,我知道推遲渲染的人有各類各樣的後處理圖像保真技術。就我我的而言,我認爲,移動到後處理圖像保真使一代遊戲看起來很糟糕,但回到主題,這篇文章的重點是從移動傳輸中刪除全屏渲染紋理,雖然他們是那麼昂貴。原本的目的是後處理AA須要一個全屏渲染紋理。在Unity,正向渲染是很是快的。我最後一次檢查UE4時並無正向渲染模式,更糟糕的是,當我問及CG水平材質定製時我被諷刺的告知「你有源」–彷彿從新編譯引擎對於垂死之人是一個可行的開發策略。這就是說,我對於若是史人正在爲它努力也不會感到驚訝。

散熱

散熱是指設備的熱輸出。做爲遊戲開發者,我熟知在移動上的幾個常見的性能瓶頸,以頻率爲順序依次爲:GPU填充率、CPU(一般繪製調用),CPU-GPU內存帶寬,GPU的頂點處和糟糕的特定設備的驅動程序問題,就像無窮無盡的GPU處理。

大部分時間這些都是不相關的問題。即便是在CPU充分利用的狀況下,開發者仍然能夠繼續添加對CPU的使用。然而,手機是小的,處理器大可能是在同一個地方,這意味着熱是一個全程問題。

爲了保持手機遠離融化,或爆炸,或融化和爆炸,當手機產生太多的熱量時將減小處理器的權限,放緩一切。當你想到硬件工程參與後能夠很可靠的作到,但幀率不能夠,這就讓人很驚訝。熱調節不是設計用來平衡性能和熱的,它的目的是爲了節省你的手機。當它第一次開始,一個很好流暢的60幀一般會降低到40幀如下。當它實現了之後手機仍然是熱的,它在相比較大的增量上減小權力。若是你的VR應用是散熱有限的,這將不是一個很好的體驗。

使熱很是具備挑戰性的緣由是由於很難知道是什麼是形成熱,忽然一切都是相關的。若是你能夠減小每一個函數調用的彙編指令,也許你能夠假定每一個指令的一些恆定的熱因子,但這沒有考慮到你的硬件效率或設備內部的物理結構,或應用程序的控制之外的因素,如後臺進程,或者wifi等等。

爲何這對於VR是獨特的?其餘一些移動應用要求高分辨率3D渲染一個恆定的60幀4x MSAA–除此以外,VR應用渲染場景兩次(每隻眼一次),大多數SDK默認渲染一個高分辨率渲染紋理進行畸變。事實證實,渲染紋理在性能和產生的熱量方面是很是費錢的。

在Gear VR發佈的時候,約翰·卡馬克提到了相關散熱的問題。不幸的是,這不是一個能夠很快消失的問題。

關鍵點:若是你的性能好幾分鐘,而後就莫名其妙地暴跌(以致於你的手機燙手),請檢查日誌中的熱警告。

頂點位移鏡頭校訂

當項目開始時,Cardboard Unity SDK的默認渲染方式是渲染成一個16位的渲染紋理不用MSAA。即便在這些設置下,許多低端設備在幾分鐘內就遇到了熱限制。GearVR使用了一個相似的管道,也遇到了相同的侷限性。不管使用什麼SDK,在手機上繪製全分辨率渲染紋理是會佔用性能的。

切換到頂點位移VR後,CDL渲染成32位全屏緩衝區(減小色帶)–根據設備利用2x-4x MSAA,而且通常維持60幀。

此外,經過對「鏡頭空間」場景畸變,咱們避免了變形的渲染對象的分辨率損失(或經過渲染一個更高分辨率的緩衝區而其相應渲染時間的浪費)。這是一種有效的像Nvidia公司最近發佈的多分辨率的陰影,但它是免費的,而且它能夠在一個6年的智能手機上運行。

上圖:使用標準的渲染紋理技術渲染的121頂點平面。

下圖:121頂點平面採用頂點位移,2x MSAA,沒有渲染紋理。UV圖像來自

http://www.pixelcg.com/blog/?p=146

 

 

從上面兩個渲染中心進行雙線性放大。

左:標準渲染紋理技術

右:頂點位移

如何使用

目前Unity的Cardboard SDK中有一個CG,其中包含一個名爲CardboardDistortion.cginc文件。它包含了一個方法,這個方法用Brown–Conrady模型進行徑向畸變校訂將一個世界空間的頂點轉換爲反鏡頭畸變屏幕空間(‘鏡頭空間’)。

使用這個功能,看起來像是一個簡單的固體顏色材質。請注意,我已經禁用了在桌面和在編輯器中使用條件編譯的效果。在編輯器中執行反鏡頭畸變,使編輯的場景至關具備挑戰性。

CGPROGRAM
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#include "CardboardDistortion.cginc"

struct VertexInput {
float4 position : POSITION;
};

struct VertexToFragment {
half4 position : SV_POSITION;
};

VertexToFragment VertexProgram (VertexInput vertex){
VertexToFragment output;

#if SHADER_API_MOBILE

///easy as that.
output.position = undistortVertex(vertex.position);
#else

///this is how a standard shader works
output.position = mul(UNITY_MATRIX_MVP, vertex.position);
#endif

return output;
};

fixed4 _Color;
fixed4 FragmentProgram (VertexToFragment fragment) : COLOR{
return _Color;
}
ENDCG

要求

這看起來很容易,你可能會想知道爲何每一個人不在每一個平臺上這樣作。爲何有人爲渲染紋理而感到煩惱?爲何咱們不把全部的東西都放在「鏡頭空間」。

鏡頭畸變是非線性的,所以,反透鏡畸變也是非線性的。當咱們對頂點着色處的頂點變形時,它們之間的線仍然是一條線,事實上,它應該是一個彎弧,當你經過一個彎曲的鏡頭看一條弧線時,它看起來像是一條線。當你經過一個彎曲的鏡頭看一條直線時,你會看到一個立方體與彎曲的邊緣,總體的但可能不是你想要的。

上圖:121個頂點的平面。下圖:4個頂點的四邊形。注意:非線性畸變是與平面被保留,但不與四邊形。

這樣作的結果是,若是頂點間隔相距甚遠(在屏幕空間),咱們將結束校訂太多畸變,當咱們轉動咱們的頭時最終圖像將顯示爲'經',這就絕不奇怪用戶有憤怒的傾向了。

也許更糟的是,全部的頂點運動將增大對象之間的深度衝突問題。

幸運的是,解決方案很簡單,咱們須要添加足夠的頂點鑲嵌,這樣失真將再也不明顯。事實證實,大多數高端移動設備可以在每幀的200000和800000個頂點之間渲染。不幸的是,咱們仍然須要渲染場景兩次,因此咱們的頂點限制在100000和400000之間的頂點,此外,還取決於你想支持的設備。

你可能會認爲,添加全部這些頂點會再次引發咱們的熱故障,但現代手機有很是密集的屏幕,1920×1080是至關廣泛的。1920×1080約有2百萬像素只有少許的透支,咱們能夠執行每幀1千萬個着色器片斷。若是咱們須要渲染成一個單獨的渲染目標爲畸變校訂,它增長了另外的2百萬像素,加上上下文切換不可忽略不計的成本和大量的紋理內存訪問。

一個好成果

由於咱們必須大量增長場景的頂點數,咱們能夠利用這一點。咱們能夠在頂點程序中運行40萬次計算照明,而不是在片斷程序中運行約1000萬次計算照明,這是計算的25倍下降(熱切但願)。因爲咱們的頂點須要足夠密集的非線性透鏡畸變,照明也可能足夠密集(這通常也是非線性)。

就像非線性畸變,頂點照明質量在很大程度上取決於頂點計數。左:使用頂點照明的4個頂點的四分之一是不能從點光源顯示太多細節;右:一個具備121個頂點的平面是距離的一個合適近似。

這裏請注意:我永遠不會使用任何Unity的着色。我從不使用他們的天空盒。我只使用他們的照明引擎原型。在CDL的每一個着色器編寫在CG/ ShaderLab(不使用表面着色器),和片斷程序或從頂點着色器中讀取顏色值而且顯示它,或讀兩顏色值,訪問紋理,經過一種顏色增長紋理並添加另一種顏色。保持片斷程序很是簡單,除去渲染紋理,減小透支使GPU多檢查。

UI和2D

還有一個用來實現一個頂點位移管道,那就是處理二維元素,如用戶界面。

既然咱們在VR,UI已是一個棘手的問題。爲了維持正常的立體融合,UI須要在3D空間渲染,最好引用同一深度的3D對象(如網線須要對遮擋對象進行3D深度渲染)。

UI須要未失真和確保有足夠數量的頂點,以及有意義的繪製UI元素,例如字母和紋理上鑲嵌的是平面而不是四邊形。鑲嵌的確切數額將取決於屏幕上的UI元素的最大尺寸。

固然,任何一個被鎖定的UI都會變形,但變形不會隨着用戶的頭部旋轉而改變,因此這種效果可能不太明顯。

至少通常VR的接口是最好的處理背景,因此但願利用頂點位移鏡頭校訂不會出現大的障礙。

優化

頂點位移的最小偏差近似是在屏幕空間的頂點之間的距離的最小化,即爲對象進一步遠離相機,他們不須要太多的鑲嵌,所以標準LoD技術是有用的。

這爲優化提供了一個明確的機會,特別是對固定位置渲染。假如相機能夠在一個場景中移動的狀況下,優化變得更具挑戰性。

最後的想法

坦率地說,我仍然感到震驚,這不是一個被普遍使用有極高硬件要求的發佈桌面HMDs技術。基於鏡頭校訂的頂點位移使智能手機渲染VR使 QHD(2560×1440)顯示爲60 幀高達4x MSAA。大多數現代的集成顯卡至少應該可以集合多性能,而低到中等範圍的專用顯卡能夠作得更好。我不但願在個人英特爾HD 5000上玩前線VR,但我不相信HMD硬件當前做品能夠很容易的獲得一個更普遍的受衆,而不須要SLI的支持。

關於Brian Kehrer

Brian是一個獨立的遊戲開發人員和圖形程序員。他是Cardboard Design Lab的ustwo(奇幻冒險遊戲)首席開發員,在那裏他花了不少時間研究着色器。

相關文章
相關標籤/搜索