​如何提升 VR 渲染的性能?手把手教你 | 乾貨


引用渲染那麼重要,VR 內容開發者,你們都造怎麼做好嗎?


本文您將了解到:

引用1,VR 渲染面臨什麼問題?

2,如何做好 VR 的渲染?
3,怎樣提升 VR 渲染的性能?

渲染對於 VR 內容的開發來説,是非常重要的議題。

但在現在的 VR 內容開發中,卻還沒有成熟的解決方案,特別是針對 Unity 開發者。

近期,VR 價值論在 VRCORE 公開課上找到一份 VR 渲染指南。

包括渲染方面的基礎知識,以及在 Unity 裏面如何去優化渲染的效率。

廢話不多説,直接上乾貨吧,內容較多,建議收藏。

本期(第 44 期)來自 AMD 的 VR 內容開發工程師王文濤在 VRCORE 公開課上的分享:如何做好 VR 渲染以及提升效率?


研究生開始,我一直研究圖形學和渲染。

渲染對於遊戲開發、以及現在 VR 內容的開發來説是非常重要的議題。

打個比方,你做房地產展示類的應用,那麼渲染就很重要,房屋內的光照,日夜之間的切換,這些都需要渲染,做的好的話,將成為讓你的應用脱穎而出的殺手鐗。

不過,渲染雖然重要,在現在的 VR 內容開發中,卻還沒有成熟的解決方案,特別是針對 Unity 開發者。

大家都知道,雖然虛幻引擎效果比較好,可以做出電影級別的畫質,但很大部分的開發者還是使用 Unity 開發,包括我自己。

Unity 的效果不太完美,不過我們不能因為它渲染效果不好,就去做一個不完美的東西。這樣不行,因為你的產品最終是要跟別的引擎做的東西去競爭。

所以,我今天來講的就是渲染方面的基礎知識,和在 Unity 裏面怎麼去優化它的效率,一些指南性的東西

這樣主要是為了大家在之後使用 Unity 開發的時候能夠有一個全局上的了解和判斷。

比如説,為什麼我的遊戲運行的這麼慢?

為什麼我的幀率這麼低?

或者為什麼我想要的畫面和遊戲運行出來的畫面差的這麼多呢?

到底是我的全局光照出了問題還是説我的抗鋸齒有問題?

在開始之前,我想先給大家看一個 Unity 做的電影。(價值論友情提示:視頻為演講者演講過程,提及的電影也可以從小視頻 3 分 40 秒處開始播放哦。)

它和傳統電影製作流程不一樣,完全是在引擎裏實時運行的。

這個也是 Unity 做出來的效果,質量很高,接下來,我們會逐步去分析它。

可以看到的是,首先,這個機器人的材質非常的真實。金屬的高光、地板上的反射。

反射在我們生活中很常見,但在遊戲引擎裏是比較難實現的技術,不管是實時的還是烘培的反射。

但它使用一些特殊的技術去實現反射的技能。這個過道光很自然,你在使用 Unity 開發的時候,打一個普通的面光源或者點光源,很難做到這麼自然的光照。

這是因為它在這裏面使用了全局光照的技術,或者叫做間接光照。

影片主題其實就是説機器人是人類的造物,或者説人類成為了上帝,這是我自己的理解。

大家看到那個電影很酷炫,有一種電影級的畫質。當然我們不考慮顯卡因素,因為剛才放的那個電影是用三塊 GTX980 去交互渲染的。VR 現在很多的開發者也有 1080 或者我們 AMD 的 FURY X,Fury Nano 這種級別的顯卡。

假如你有一塊這麼好的顯卡,你怎麼做出一個非常牛逼的畫質呢?

怎麼理解渲染?

引用性能

有兩點要求需要滿足。

  • 在某個固定的平台上必須要達到一定的幀率。

就是説,看起來至少每秒得能夠有 75 幀,其實必須要達到 90 幀才不會暈眩。

  •  必須要滿足遊戲設計藝術家的要求。

這並不是説特效堆的越多越好,或者説做出來的渲染越真實越好,並不是這樣。

比如説,你的遊戲可能是水墨風格,可能是美術風格。你用現有的技術把它做的非常漂亮,這是一個很好的渲染系統所必須擁有的特性。

我們想到的現在比較優秀的作品,比如説《使命召喚》或者《戰地》。為什麼它們能夠在 PS4 上跑出這麼優秀的效果?

除了美術過硬之外,他們也使過非常多的光照、貼圖、建模上的技術去實現效果。

當然,在 VR 裏面,這些渲染實現會更加的難。

因為大家都知道,VR 是兩隻眼睛,通過左右眼的視差去產生立體感。

首先,至少要渲染兩個 runnertarget,也就是説兩幅圖像;

其次,平常我們使用的 PS4 或 PC 上的分辨率 1080p 已經非常高了,現在渲染的分辨率要 2k(HTC 的分辨率是 2k,Oculus 的分辨率也是 2k 以上),兩隻眼睛,同時幀率還不能説只達到 60FPS,而必須達到 75FPS 或者 90FPS。

在這種情況下,你必須要犧牲掉一些效果。甚至説,你要犧牲掉很多效果去達到基本的性能要求。

在這個情況下,優化就顯得非常重要。

引用鋸齒

還有一個比較重要的因素,就是我們在 VR 裏,眼睛離屏幕非常近。

同時,我們的眼睛一直在運動的。

那麼,我們平常在用電腦玩遊戲或者手機玩遊戲的時候,一些比較不明顯的畫質上的差異它就會體現出來,特別明顯的就是鋸齒

玩遊戲比較多的人知道有個名詞叫 “狗牙”。比如説一個非常細的多邊形,我看上去會有一段一段一段的 “狗牙”,或者説一塊金屬反射的高光,我在玩的時候它會不停的閃爍,就會讓人感覺畫面很不穩定。

而在 VR 裏面這種情況更加的嚴重,也就是我們通常説的抗鋸齒會變得更加的重要。

怎樣解決性能上的問題?

我先講一下,怎麼解決這些性能上的問題。

引用減小渲染圖像

首先,一個比較自然的想法就是把要渲染的圖像變得小一些

那麼怎麼變的小一些呢?

一個很明顯的優化思想就是,渲染並不是説兩幅圖都是 2k 的圖片,並不是要把這 2k 全部渲染出來,因為現在的頭顯是有 FOV 的,它在邊緣是有畸變的。

也就是説我們完全是可以只渲染中心一部分的圖片,而並不是把整個圖渲染出來。

用一個遮擋的 Mesh 去把不需要的像素點剔除掉,對你真正的體驗來説不會有任何影響。

舉一個例子,Valve 公司做的《The Lab》的 Demo。

在這裏面就講到,用一個圓形的 Mesh 去保留所需要的像素。邊緣那些黑的在 VR 頭顯裏面,或者説在 HTC Vive 或 Oculus 裏面不需要這些像素。它測算出來的結果是,通過這個能夠把 17% 的像素去剔除掉。這是一個比較自然的想法。

引用注視點渲染技術

還有一個類似的想法,像素的着色或者説像素的渲染,是 GPU 裏面損耗最大的部分,那我們能不能把這些像素不要再去扔掉呢?

其實最簡單的思想是,人在看東西的時候是有一個焦點的。

打個比方説,我現在看到的這塊屏幕,我的眼睛會集中在這塊屏幕上。我不可能太多的關注周圍的窗簾、包括這塊廣告板。

那是不是説,我們可以把更多的 GPU 的效率提供在這塊板(焦點)上而不是我們同樣的渲染整個視場中的,包括這邊和這邊的物體。

這就是一個非常簡單或者説非常直白的叫做 Foveated Rendering,就是注視點渲染技術

傳統的渲染流水線中,我們會把三維空間的物體投影到屏幕上,然後每個像素都一個一個地按部就班的去着色。

實際上在 VR 裏面,它還真不是這樣。因為在 VR 裏面我們有注視點,可能説我們只看中間的那一小部分,而並不是説我們對整個的畫面中的像素都是一視同仁的。所以説,有一個非常簡單的實現技術,固定的注視點渲染,它並不是説我們需要實現眼球跟蹤那麼複雜的技術。

比方説,我在看的時候,我的眼球會往這邊看或者往那邊看。

我們做一個最基本的假設,就是説我的眼球總是看着最前方,然後我們通過一個算法把周圍像素着色的密度去降低,那就可以提高很多的效率。

這裏説的 GameWorks VR,也就是英偉達推出的關於 VR 渲染的技術裏面,也用了同樣的思想,就是 Multi-resolutionshading。

這個思想其實是一樣的,它就是説我也假設我的視點永遠是在畫面最中心,然後我把畫面分成大概 9 個區域,分別按不同的着色密度去渲染。

我看過官方的數據,這個 Multi-resolutionshading 能夠提高 15% 或者 20% 的着色效率。

還有一個比較浪費的就是,在 VR 裏面你要渲染兩遍,左眼和右眼。

其實很多東西是不需要渲染兩遍的。

最基本的就是説,和燈光有關的東西,你根本不需要渲染兩遍。

  • 比如説 Shadow map,也就是陰影

因為,陰影是跟燈光有關的,和攝像機的位置無關。你的兩隻眼睛不管距離多大或者是差異性有多大,它都是一樣的。

  • 還有一個比較值得研究的就是,比如説漫反射

高光我們可能在兩個眼睛裏面會有很大的區別,但是漫反射其實區別比較小。

  • 再一個就是説,比如説很多的後處理的特效

比如我們的光暈、HDR 高動態範圍,這個特效其實都不需要渲染兩遍。

所以我推薦,基本上大家在做 VR 開發的時候能夠用 Unity 5.4,雖然現在還 Beta 版,但在 5.4 裏已經開始對這些東西做了一些優化。如果你用 5.3 的話,可能效率還是要低一些。

怎樣解決鋸齒上的問題?

然後我再講的就是剛才説的鋸齒問題

這個東西在 VR 裏面會是一個非常嚴重的問題。

大家都知道 Unity 裏面攝像機可以設 render pass,包括有前向渲染 Forward Rendering 和延遲渲染 Deferred Rendering。

在 VR 裏面我們怎麼去選擇這個呢?

你在做一個小遊戲的時候,可能根本不會 care 這個東西。

用前向渲染和用後向渲染,顯卡都是能夠滿足目標的。但是,我在這分析的就是説前向渲染,它有一個天生的好處就是能夠在硬件上支持 MSAA。

我們玩遊戲的都會知道一個選項,如果你去把《使命召喚》或者這樣遊戲裏的圖形選項打開,它有一項就叫 MSAA。

MSAA 實際上是顯卡里用硬件算法去支持的。

如果你用前向渲染,它天然就自帶了一個 MSAA 的效果,鋸齒問題就不是那麼嚴重。

但後向渲染其實就是一個非常尷尬的事情,如果遊戲玩的多的可能都知道,現在有抗鋸齒的 FXAA,其實是基於一個圖像分析,這個圖像分析在 VR 裏面用處並不是很大,或者説即使加上了對於鋸齒的改善並不是很明顯。

所以,我向大家推薦 Unity 裏面非常強大的插件,就是 VALV 的 Lab Renderer。

其實這是 VALVE 的工程師在做 The Lab 這個 Demo 的時候,想到的這個事情。

如果你聽過他們在 GDC 上的演講,就會明白他們也用 Unity 做開發,那他們為什麼不用 Unreal 呢?

VALVE 做的《半條命》、《DOTA2》,是非常高端、特效非常好的遊戲。為什麼它要用 Unity 呢?他們工程師就説了一句:“我們發現用 Unity 的團隊,大部分都是小團隊,而這樣的小團隊裏面是不可能有一個人去專門研究圖形,專門研究畫面效果的,所以我們去專門研究這樣一個插件叫做 The LabRenderer 的技術。”

目的就是説能夠幫助小團隊去實現一個還不錯的渲染效果

這個渲染其實特別容易。

它就是最簡單的一個 pass forward renderer 前向渲染器

能夠最大的支持 16 盞動態光源。我想 16 盞動態光源對於絕大多數遊戲或者非常複雜的應用來説都是夠用的。

它最大的特點就是説 MSAA,能夠天然支持 MSAA,鋸齒是非常不明顯的。它天生就自帶了我剛才説的那些注視點渲染、像素剔除這些技術。相比 Unity 默認的渲染,你使用它渲染會有非常好的效率上的提升。

但然,它也有一些限制。

引用它必須用自己的 Shader。

比如説你在 Unity 用慣了標準材質,或者你自己買的一些 Alloy Shader,貼圖就要重畫或者重新連接材質的節點。

用這個插件需要你去做一些修改。

當然,如果説項目並不是很大,我非常推薦使用這個東西。去學習一下它的流程,一個是對你自己,對整個團隊的圖形學知識是個很好的。

另外,它整個代碼是 open source,在 asset store 上,搜 The Lab Renderer 就可以下載,不需要掏錢。

再一個就是説,你不用花時間去糾結一些比較基礎的東西。

比如 Unity 沒有注視點渲染、沒有像素剔除的技術。那你看一下用 Unreal 開發的,天生就自帶 Gameworks VR,人家做出來為什麼這麼快。你自己如果要花時間去寫,花時間去研究,這就是一個非常大的工程。所以 VALVE 給你搭的這一套東西就節省不少的時間。

然後我講一下,前向渲染對於我們來説並不是一個非常完整的解決方案。特別是 MSAA 對於比如説高光的鋸齒並不是能夠解決的很好。

那麼我們在 Unity 裏面是不是有別的更好的技術去解決它?

我在這裏強調的是前向渲染對於多光源並不是非常有效率,包括剛才説的,可能只能支持 16 盞光源,再多它的幀率會下降的非常快。

即使是支持到 16 盞光源,也並不推薦你完全的用滿它。

再一個是,比如説,我們很想使用一些特效,比如屏幕空間反射。但這個東西對於前向技術就沒有辦法實現,因為屏幕空間反射需要用到屏幕的幾何信息,那怎麼辦?那我們是不是有一個更好的方法?

還真有。

大家想一想,我們做電影和做遊戲的區別是什麼?

做電影其實是一個追求質量的過程,做電影一幀可以渲染 1 個小時、2 個小時。但做遊戲,或者説做 VR 內容開發,我們需要的是效率,一幀最多是十幾毫秒。如果你超過 20 毫秒,那這一幀基本上完蛋。所以説,電影上的一幀可以一直渲染下去,直到它收斂為止。

那麼,渲染在圖形學裏面其實就是一個不停採樣的過程。

而抗鋸齒根本的來源就是,一個渲染的圖像,它缺少信息,大家如果是工科或理工科出身的,就知道 “奈奎斯特採樣定理”

我的採樣頻率要高於我最高頻率的兩倍,我就能完整地恢復出我需要的信息。

在渲染這個領域其實也是一樣。

打個比方説,我們大家都知道,最簡單的抗鋸齒的方法是什麼?你渲染一張 2k 的大圖,把它縮小到 1k,那這張圖肯定鋸齒非常少。

為什麼?因為這相當於我們對 1k 的圖的每一個像素做了四次採樣。但是實際上,你真的去渲染一個 2k 的大圖,那麼 VR 有 2k 我可能就要去渲染 4k,你這樣去抗鋸齒顯然是不行的。

後來就有聰明人説,遊戲最大的特點是連續性,那如果我能夠找到每幀之間相同的像素,那我就能在時域,也就是説很多幀之間去做個採樣。

就實現了個超採樣,也就是所謂的 Super Sampling。

有的時候大家在數據信號處理的課裏面,提到這個 Super Sampling。這個能夠很好的提高畫面的質量,最關鍵的是這個很便宜,或者説並不是很好,當然它的實現難度是有的。

我給大家看一個具體的例子。這個 Demo 挺有名的,使用虛幻引擎做的。這個是沒用時域抗鋸齒的結果,大家看到最大明顯的特點是閃。因為,整個畫面高光的東西太多了。如果説你不用抗鋸齒,畫面會非常不穩定。這個地方會特別的閃。

我們加上了時域抗鋸齒的結果,是什麼?

最大的特點就是整個畫面非常穩定,這樣看起來是不是就有電影級別畫質的感覺。畫面穩定、像素沒有任何瑕疵,包括在高光的地方也不會閃,非常的穩定。

我剛才説的 Temporal AA 一樣的,在 asset store 上也可以找到一個還不錯的實現。我不知道大家知不知道 limbo 這個工作室,可以去搜 limbo 的 taa,能夠得到非常不錯的 Temporal AA,也是直接在 GitHub 下載就可以了。

我想跟大家建議,要擅於利用包括 GitHub、Asset Store 這樣的插件讓我們的開發提升效率。

如果你想做很棒的產品,你必須要擅於利用這些前人已有的資源。

怎樣解決全局光的問題?

然後,我再講全局光的問題。

全局光問題歷來是遊戲裏比較頭痛的問題,特別是在 VR 裏面更麻煩。

什麼叫全局光照?

比如一個燈打到一塊黑板上或者地板上,它投下來的影子那是直接光照。但如果它在地板上反射出去的光線照亮了其他物體,那這個就是全局光照。

全局光照一般是通過烘焙,也就是離線的方法把全局光照存成某種數據結構,在遊戲實時運行時調用去實現的。

但在 VR 裏面對於實時的運算是要進行嚴格的限制,所以我不推薦大家在 VR 裏面使用實時的全局光照技術,比如説提速、mpv 這種技術。
我建議大家老老實實用標準的光照貼圖,也就説烘焙一張貼圖然後貼上去。

但是,Unity 又是一個非常麻煩的問題,Unity 自身所帶的 enlighten 的烘焙,不是很好調出非常好的效果。

我想大家可能都看過 Unreal 的一些作品,比如説 Unreal 做的室內裝修,為什麼室內裝修企業,比如説 51VR,他們都會用虛幻引擎去做室內裝修呢?

一個最大的原因,室內裝修對於全局光照的要求非常高,Unity 是達不到的。如果你是用 Unity 做東西,用 enlighten 去調一個非常好的全局光照,難度很大或者説幾乎不可能。

所以,我推薦大家儘量去使用另外的烘焙工具,比如説 vRay

當然,你把它導進 Unity 裏面是需要耗費一定的工作量,但是這個比你去用它自帶的烘焙工具要好一些。

我們這邊也做過嘗試,如果真的去用比較優秀的烘焙工具的話,Unity 做出的室內設計或者室內展示的質量是不會輸給 Unreal。

當然,還有屏幕空間的技術,大家都知道屏幕空間的技術關鍵就是在於快,缺點就是精度不夠

比如 Unity 自帶的 SSAO 這個就是一個非常好的實現,但在 asset store 有 HBAO 或者是別的 AO 技術,大家都可以試一下。

我建議大家能用就用,在硬件夠、本來全局光很矬的情況下,你沒有這些 AO 補償的話,畫面會比較挫。

再一個就是屏幕空間反射,屏幕空間反射現在在 5.4 的 beat 版裏面官方已經有了,其實你們只要在相機上加上 imagine facts 裏面就會有這個。

當然實現的屏幕空間發射在 Unity 5.4 實現可能不是那麼完美,但其實它已經是夠用的。

如果場景裏有非常多的金屬物體,或者説非常多的鏡面,使用反射的話會大大增加你視覺上的觀感。

打個比方説,我是在一個很空曠的金屬競技場裏面,甚至説我只要有空間反射的技術可能不需要 GI,就能給人一種非常好的視覺上的表現力。

説了這麼多,我覺得其實優化還是那套方法,大家都知道的,簡單説減少 drawcall、減少 DC、batching。

Unity 的 batching 這個東西是一個老生常談的話題,在百度、Google上一搜會有很多相關詞條。

怎麼去 batching?在場景裏怎麼去 batching?

在 VR 裏面,要求會更高一些。

比方説,我聽過一個講座,《Gunjack》就是在 GearVR 上實現的遊戲,它對 drawcall 這個東西限制就非常嚴,它每隻眼睛的 drawcall 不能超過 50。

所以,不管你是開發 HTC 或者是開發什麼樣的應用,drawcall、batching 這些東西一定要非常的注意。

你不能無限制的堆你所需要的東西,而是説做一段時間,可能就要運行一下,用 Unity 的工具去看一下,我現在這個場幀率是多少?我到底在哪裏耗的特別快。

還有一種比較好的方法就是説,實在不行就按藝術家的方法去畫

打個比方説,bloom 光暈特效,這個東西大家都知道 Unity 裏面有 shader 自帶,但是這個佔的時間。

如果你是做移動平台的,你可能知道移動平台後期處理的效果是非常佔時間,那怎麼辦?直接美術畫上去,這也是非常行之有效的方法,當然也考驗你美術的能力了。

再一個,我推薦多去測你遊戲的性能。包括 professional unity 5.4 裏也已經是比較完善的一個東西。

多去測性能、多去了解你遊戲的瓶頸、bottleneck 在哪裏、是 shader 太多了還是説我某個特效真的不該用。不要在編輯器裏測,最好是打個光。

對於開發者的建議

最後説一下,渲染有一個自我的評估。

當然我知道現在的很多團隊是不會專門有一個程序員、或者專門有技術美術去關注這一塊的。

但是我想説的就是,希望大家能夠去多考慮一下。

比如説,你所需要的特效的特點是什麼?

比方説,如果做的是一個機械的大戰,你可能非常需要反射,可能就會去使用一個屏幕空間反射的特效在 Unity 5.4 beta 版裏面會有。

再比方説,你做的是一個互動電影,那麼對畫面的要求會非常高,那麼抗鋸齒就要做的非常出色,那你只能使用時域的抗鋸齒 temporal AA,我剛才説的那種方法。

具體問題具體分析,渲染這個東西,永遠不是一成不變的。

它不是像電影渲染一樣,只要渲染的夠真實或者説只要去模擬每一根光線的運動軌跡,就得到一個非常完美的圖像。

關鍵在遊戲裏面,根據美術風格去做出妥協,根據性能去做出妥協,所以這是一個永遠會談論下去的話題。

你很難去説,我某個引擎特別牛,任何遊戲都能做。即使是效果這麼好的虛幻引擎,它也很有可能也有做出來幀率非常低的情況。

如果你不懂,不懂刪減特效的話,你最後很有可能遇上非常大的麻煩。Unity 的幀率並不是一個很大的問題,但是它的效果同樣是個很大的問題。

如果你不懂得怎麼通過各種各樣開發,包括 shader 的技巧去加特效的話,也可能很難做出非常優秀的作品。

所以,我希望大家能夠多討論,有問題就提出,甚至能夠建立一些自己的 library 或者 open source library,去提高整個 VR 社區開發者的質量。

資料來源:愛範兒(ifanr)

如果喜歡我們的文章,請即分享到︰