為什麼遊戲里的鏡頭虛化「尤其是近景人物」總看起來不太自然?

做了一張示例圖(點擊可以放大),感覺遊戲里一旦出現人物虛化效果,往往會呈現出圖 3 這種不自然的樣子,輪廓看起來過於銳利。

請問是什麼原因造成的?想要解決又有什麼技術難點呢?


多圖(9P)長文(將近兩千字)預警。為了盡量避免過多的專業性內容,難免有些描述不盡準確之處,歡迎大佬指正和補充。

這一問題源於遊戲引擎實現虛化的具體方法,以我個人比較熟悉的虛幻4引擎為例吧。

首先明確一點:所謂「虛化」是在模擬照相機拍攝照片時,景物處於鏡頭焦距之外而產生的成像模糊效果,在遊戲中用於營造類似電影的視覺感受,或者指定對焦物體來使玩家對特定物體集中注意力。這種效果在遊戲引擎中被稱為「景深」(Depth of Field,簡稱DoF)。

如上所述,景深是一種模擬攝像機鏡頭效果或者引導玩家注意力的工具,而不是用來模擬真實視覺效果的——人眼只能對視野中央的一小塊區域清晰成像,但是人眼變焦非常迅速,並且大腦中的視覺中樞會與眼睛互相配合進行圖像處理,這導致人實際上是不能看到景深的,正常人眼往什麼地方看都會迅速變焦到合適的狀態清晰成像(除非實在太靠近人眼,或者人眼有近視、遠視等生理障礙),於是「真實的」視覺效果中不存在景深模糊。

因此這裡所說的景深盡量自然,指的是景深效果盡量接近攝像機拍攝的焦距外物體的效果。

遊戲引擎想要獲得一個物體和攝像機之間的距離是很容易的,理論上只要按設定的焦距,對焦外物體施加一定量的模糊效果就能模擬出景深。這就是虛幻4最簡單的一種實現:高斯景深(Gaussian DoF)——得名於其所採用的高斯模糊方法。

圖1. 高斯景深的效果圖示

然後是一種性能消耗相當大、但是更加接近真實鏡頭散焦效果的方法,稱為散焦景深(Bokeh DoF)。

圖2. 散焦景深的效果圖示

後來虛幻4還加入了一個名為圓景深(Circle DoF)的東西,屬於一種性能優化的散焦景深,原理上類似,所以這裡就不多說它了。

觀察上面兩張圖,可以看出焦距外物體(特別是左側的近景物體)在高斯景深中是簡單地模糊成一片,而在散焦景深中(特別是高亮度的部分)則像是很多層層疊疊的多邊形光斑——後者顯然更接近一般的光學鏡頭散焦時拍出的效果,其「塗抹感」要弱一些。

但是這兩張圖中的虛化,都不同程度地在近距離時距離突變的位置(例如左側人形與身後陰影牆壁之間的邊緣)出現了不自然的「模糊區域的銳利感」,而遠距離(例如右側景物)則沒有這種現象。其原因來自虛幻4引擎判斷「應當給這個區域進行何種程度的模糊」時的方法:

圖3. 像素紋理到鏡頭的距離與其模糊程度的關係

如圖,引擎依照每個像素點紋理和鏡頭的距離將其分為五類:距離鏡頭非常近的近景(左側綠色區)、距離鏡頭非常遠的遠景(右側藍色區)、正好處於焦內的聚焦區(中間白色區),以及近/遠景和聚焦區之間的過渡區(綠/藍色到白色的漸變區)。在近景和遠景區,模糊程度都是最大,在聚焦區完全不模糊,而兩個過渡區的模糊程度則與聚焦區和近/遠景區之間線性過渡並連續。

引擎的分類結果如圖所示:

圖4. 引擎獲得的近景、聚焦區、遠景圖層分布

上圖中綠色為近景,藍色為遠景,黑色為聚焦區,漸變為對應過渡區。引擎正是依靠這張圖的信息對場景進行模糊處理。

而真實的光學鏡頭拍攝的同時含有近景、焦距內景物和遠景的照片是這樣的:

圖5. 來自必應主頁壁紙

如圖5所示,在真實的鏡頭散焦中,近景-焦距內景物的邊界(為便於敘述稱為A型邊界)和焦距內景物-遠景的邊界(B型邊界)有明顯不同:由於A型邊界是近景(模糊)遮擋焦距內景物(清晰)產生的,而B型邊界是焦距內景物(清晰)遮擋遠景(模糊)產生的,因此A型邊界本身是模糊的,而B型邊界是清晰的。換句話說,如果近景遮擋了焦距內景物,那麼它們之間的邊界應當是模糊的;而如果焦距內景物遮擋了遠景,那麼它們之間的邊界應當是清晰的。圖5顯然可見這一現象:左側焦距內的植物葉片遮擋遠景形成了清晰的B型邊界,而右側近景植物葉片遮擋焦距內植物葉片,則形成了模糊的A型邊界。

我們現在來具體考察圖1/2中的左側區域,也就是人形腿部與身後牆壁之間模糊程度不自然的跳變。左側人形腿部與身後牆壁間(圖4中左側的綠色和黑色部分)形成了典型的A型邊界,即模糊的近景遮擋清晰的焦距內牆面,二者之間應當產生模糊的邊界。但是在圖1和圖2的實際渲染中,這個邊界是相當銳利的。由於圖4是依靠立體模型與攝像機的相對位置信息計算得出,用於標識近景的綠色人形與實際的人形圖像是完全一致的,綠色人形的邊緣就是場景中人形模型的邊緣。而引擎老老實實地依靠圖3中的方法對圖4中綠色人形區域進行了高度模糊,對黑色牆壁區域不做模糊。這就導致了「模糊」被限制在了綠色區域內,完全沒能和黑色的牆壁區域進行混合過渡,從而產生了不自然的銳利的A型邊界。

解決它的方法很簡單,虛幻4的景深系統提供了現成的Occlusion(封閉)屬性,用於定義模糊形體的半透明輪廓「泄露」出原本輪廓的程度。適當調整該屬性就能得到效果很不錯的A型邊界:

圖6. Occlusion = 0.05

圖7. Occlusion = 0.18

圖8. Occlusion = 0.40

不過很多遊戲中確實仍然存在明顯不協調的銳利的A型邊界,例如巫師2在打開「電影景深」選項以後就是重災區:

圖9. 模糊的近景傑洛特對清晰的焦距內羅契遮擋仍然產生了清晰的A型邊界

或許不這麼做是出於性能方面的考慮,畢竟多一步處理步驟就要多花一點時間,而遊戲渲染一幀的時間能多壓榨出一毫秒,幀率就會有顯著提高;也或許是出於「景深就是用來讓玩家注視清晰的聚焦部分的,非聚焦區域質量差點沒關係」的實用性考慮。

參考資料:Depth of Field


簡單來說,現實攝影機鏡頭範圍里的每一點光,經鏡片投射至感光平面時會變成 Circle of Confusion(CoC)。在渲染時,理想地是在後處理時逐像素把深度轉為 CoC 大小,然後按大小把像素顏色畫成 Bokeh 疊加。但現在的硬體中,這種 scatter 運算比 gather 運算慢,所以不太適合使用。
現時的方法大多數是先用 gather 運算做模糊,然後再混合結果,會出現問題中的瑕疵。
如果要真實,可 distributed ray tracing 鏡頭的鏡片組,但要實時還要等硬體的進步。


哈哈!Dof演算法問題(depth of field),如果你玩實時渲染,可以自己搜搜相關主題、演算法等等。(搜關鍵字「dof gpu gems」你可以獲得一篇很有實踐價值的文章)

看完後你就會知道,這麼個看似簡單的效果,實現起來有……多……難!比大名鼎鼎的SSAO難至少50倍。比想像起來難多了。

剛學ogl那會兒,我一拍腦袋就想,不就是來一個post processing,然後根據depth來調節gaussion blur的強度就能實現嗎?

後來一試,效果像屎一樣,然後在gpu gems的某一期里找到一個Infinity Ward提出的實現方法。怎麼說呢,反正我是勉強能看懂,但有一種不想再看第二遍的感覺:)


簡單的說以下:

現代遊戲里這個效果叫做bokeh

做法是用渲染出的depth buffer與焦距做計算 算出Circle of Confusion(錯亂圓)

根據每個像素錯亂圓的大小來進行不同強度的「模糊」操作

但是bokeh這個效果是有front bokeh和back bokeh的(形成原因參見李簡回答第三張圖)

front bokeh:

back bokeh:

以上圖源:Pentax SLR Talk Forum: Digital Photography Review

由於遊戲僅僅是根據錯亂圓的大小粗暴的進行了模糊,所以無法體現出兩種狀態的區別。

就算是根據錯亂圓進行採樣也會缺失信息造成瑕疵。

據我所知沒有什麼太靠譜的解決辦法。


這是目前遊戲里DOF演算法的問題。主流的方法是使用gather based的方法,大致流程為:

1、對於每個像素,根據深度計算CoC大小。

2、對於每個像素,以某種採樣分布採樣領域內的像素求均值。

3、混合回原來的圖像。

問題出在第三步混合。如 @黑魔姬 和 @李簡 所言,前景在處於焦外時有一個溢出(bleeding)到清晰部分的效果(或者叫部分遮擋,partial occlusion)。很多遊戲在把算完的DOF結果混合回原圖像時,只是簡單地使用了當前深度或者CoC大小做混合權重,會導致這一溢出效果的丟失。

這個問題使用gather based方法也是可以解決的,Siggraph13上Crytek就提出了一種改進方法,大致流程是:

1、對於每個像素,根據深度計算CoC的大小,保存在RT的alpha通道里

2、在進行blur前,將當前像素rgb值乘上之前算出的CoC值。

3、對於每個像素,以某種採樣分布採樣領域內的像素求均值,也就是blur。注意,這一步不僅要blur RGB值,同時還要blur alpha通道的值。

4、clamp alpha值,將RGB值除以alpha通道恢復原色。

5、使用blur過的CoC值將RGB值混合回原圖像。

這是Crytek得到的結果

參考:

CRYENGINE 3 Graphics Gems

Next Generation Post Processing in Call of Duty: Advanced Warfare


這個可以通過對深度圖再做一次down sample來改善


雙攝虛化也有類似的問題,邊界過於清晰,這麼做在人物清晰背景模糊時沒啥問題,人物模糊時就很假了,不僅如此,模糊和鏡頭虛化還有別的區別,比如光斑,當然虛化演算法也增加了光斑,所以好看的虛化並不是單純的柔化,為何要說如同奶油般化開就是因為這個,好的演算法可以更好的模擬。 具體的原因坐等大神分析。


現實中你眼睛看哪,那確實是在看那,但遊戲程序不知道你的眼睛在盯著顯示器的哪個位置啊。
算是自己瞎胡想的吧,沒有任何專業知識


因為真實的虛化就不是這樣的,或者說實際上人眼根本看不出虛化,因為人眼的彌散圓就是很小。

現實中看到由景深造成的虛化,最主要的特徵是重影,或者說視差,而失焦幾乎看不出來,因為在這個距離上,即使人眼對到最遠的焦距,彌散圓也很小,除非你把東西放眼前,尤其是在近視的情況下,看近處的東西不可能有明顯的失焦模糊。

你完全可以試一下,眼睛平視遠處,把手機舉到眼前,能不能看清手機上的字?然後逐漸上手機靠近,在離多近你才能觀察到明顯的失焦?

然而不用3D顯示你根本做不出來視差,所以就只好用失焦。但是甚至模擬眼睛的彌散圓都很煩,就只好用別的方法來做。

所以就違和了。

同樣近景和遠景邊界為什麼有違和,因為真實的景深效果是視差造成的,在某一點左右眼分別看到近景和遠景,所以邊界處會同時有近景和遠景的圖像,從而產生一種半透明的效果,而且因為主視眼的原因,遠景會比近景強,這和失焦產生的半透明效果就不一樣。

更不用說你給出的圖像近景直接把遠景蓋住了……因為根本就不是用彌散圓做的。


通俗一點的說,就是遊戲中一種模擬的焦外成像虛化效果只是模糊,並沒有採用模擬鏡頭模糊的方式。自然沒有模擬出真實環境下的景深層次感。以至於顯得不真實。
能不能做到呢,其實是可以做到的。但是這種模擬真實環境的景深效果需要大量的運算再目前的硬體基礎上採用此種效果還不能保證幀數流暢。所以就成了景深效果「很假」。


推薦閱讀:

遊戲界有什麼經典至理名言?
如何看待貼吧里的十五六歲就用引擎寫遊戲的開發者?
為什麼做成一個遊戲後,比較難做出下一個成功的遊戲?
如何評價網頁遊戲《仙俠道》?
為什麼中國的遊戲開發製作技術那麼落後?

TAG:遊戲 | 遊戲開發 | 遊戲引擎 | 計算機圖形學 |