《我的世界》 中的環境陰影(Ambient Occlusion)是如何實現的?

《我的世界》 中的環境陰影(Ambient Occlusion)是如何實現的?

有ao和沒有ao畫面效果差距巨大。

是直接用shader還是需要創建方塊的時侯生成ao貼圖?

u3d下如何實現?


此AO非彼AO吧

minecraft的所謂AO

稍微看了一下

恐怕就是根據方塊的鄰接關係

修改頂點的顏色

說簡單點 就是一個頂點如果被4個方塊共享 * 0.0

3個 就*0.33

2個 就*0.66

1個 就*1.0

之所以是4個因為 有4個方塊 不影響結果

之所以手機版才有

是因為這個幾乎沒有代價......

電腦默認開


不是shader,也不是ao貼圖,而是在創建方塊的時候計算頂點色。

minecraft中用到了兩種方法來計算頂點亮度

一種小範圍的,根據相鄰的方塊夾角計算頂點顏色的,

這種有夾角的地方會暗一些

(此圖片來自網路,Ambient occlusion for Minecraft-like worlds) 還有一種是大範圍的,利用亮度擴散來實現的,首先將垂直方向上沒有障礙的空氣方塊標記位亮度16

然後光線朝相鄰格子擴散,每擴散一格亮度減1,一直到0為完全黑暗,所以minecraft裡面亮度只能擴散16格

燈光之類的點光源,以類似方式實現,將光源所在位置標記位16,然後向外擴散


如 @山東秀才所說,一共涉及兩種效果。

一種block頂點級別的AO;另一種比起說叫一般的AO,更像是一種簡化的GI。

第一種其他答主已經解釋了。

補充一下個人之前的經驗。算面頂點的(鄰接)遮蔽方塊數的時候,應該只算面法線這邊的。

另一種AO,或者說簡化GI那邊,大概思路如下。

有兩個大步驟,第一步我稱之為injection(注入);第二步為propagation(傳播)。(讓我想起Crytek的LPV 233)

---

「GI」計算

injection步驟的時候:

1、縱向從最頂上一個格子開始,向下所有全透明格(air block和玻璃之類的)全部標記為16亮度

2、將所有具有發光屬性的block標記為該種block的亮度值

然後是propagation:

需要傳播多少格就要迭代多少次。MC最大亮度為16,最多迭代16次。

每次迭代對每個格子:

1、如果這個格子是不透明格(opaque),那麼continue

2、否則,檢查周圍六個方向上的格子,將這些格子的亮度值減去後其遮擋值(空格子或者玻璃之類的遮擋值為1,其他樹葉啊半磚啊水啊啥的大於1)後,取六個之中最大的作為本格的亮度值。

迭代次數夠了以後,最後每個格子會對應一個亮度值。

---

最終頂點光照

上面算出的是格子(或稱block)的亮度值,還需要轉換到最終頂點的亮度。

基本原則是,生成的Quad,面向的那個block的亮度值是這個quad的亮度值。然後還有個block之間亮度平滑過渡的演算法,我已經忘了,不過自己試試看嘛。分析解決問題是個很有樂趣的過程23333

然後乘上前面那個頂點級別的AO。大概50%濃度(in sRGB)樣子。

---

吐槽

雖然MC的代碼很爛,但是這個偽GI的思路倒是非常有趣,深得我心。

雖然看起來效果相當好,單步的計算量並不小,但並不需要頻繁更新,因此實際上開銷相當的低,在移動平台上也能非常流暢。而這種計算方式又和block組成的世界剛好搭調,有種莫名的elegant的感覺233。

MC火了以後有很多遊戲競相模仿,各種什麼動態陰影之類的用得飛起。結果要麼暗處一片黑,要麼平板一塊沒層次。什麼有用沒用的東西抄抄抄,MC光照系統這種有趣又好用的東西反而不抄。其實只是技術力不夠吧(笑)。

---

對改進的思考

injection很有改進空間,比如不止從一個方向(上方)注入環境光。這樣的話,可以改善一些大結構(比如巨大的懸崖)因為傳播距離超過16格而發黑的問題。

同時利用新的技術,可以把這些計算從CPU挪到GPU上。這樣也可以使用cone tracing之類的來改善GI的傳播效果。

還有可以也將陽光進行注入,這樣可以配合實時光照(傳統的shadow map)一起實現更好的GI效果。

如果將voxel數據移入GPU端計算的話,還可能使用voxel數據進行簡單的raytrace做水面的粗略反射。如果再配合上SSR的話,或許可以做出質量挺高的反射效果。


瀉藥。這個AO是移動版獨有的功能嗎?我還沒有見過這個效果(其實上面幾張圖哪張開了AO我都看不出來)抱歉。希望能多給一些提示。

順便一提,MC是用固定管線渲染的,根本沒shader


沒有實際玩過我的世界,也不是做手游的沒深入了解u3d,只說SSAO技術。SSAO這個東西本身就是針對室內場景缺乏光照又沒有GI的情況下提供的近似方法,在實現方面也不算複雜,只是在屏幕空間做遮蔽值的計算,這個遮蔽取決於兩點,第一是周圍遮蔽點和被遮蔽點的相對位置,第二是視線和遮蔽點法線的夾角,在一般的延遲渲染框架下這些都可以從gbuffer讀出來,然後計算就好了,而且自從SSDO這個東西出現後,現有的SSAO的方法基本就可以被這個方法取代,SSDO擁有更好的表現效果和相近的計算開銷,CE3用的應該就是SSDO,至於u3d應該是提供兩套解決方案,一是走烘焙把陰影AO全部烘焙到光照貼圖上,二是走相應的SSAO的後處理估計。


這個我也研究過,我用了一個自己的方法,比起mc的來效果好很多,開銷稍微大點,不多,其實這個實現方法很多,因為畢竟是規則的voxel,用紋理效果也不錯,ps:我這個模型是我朋友做的,不是我,我只是用來試驗,他名字叫gltracy


移動平台我只看到 minecraft 有ao效果


推薦閱讀:

遊戲中的一些操作很難的bug是如何被發現的?
工長君為什麼離開燭龍?如何評價他的職業生涯?
如何評價古劍奇譚方蘭生的情感線?
to the moon 結局最後的紅光是什麼意思?
為何大多數rpg都是法師最強,刺客最弱?

TAG:遊戲 | 遊戲開發 | 我的世界Minecraft | 遊戲開源 | shader |