2015年9月8日 星期二

THE BLACKSMITH中獨特的角色陰影

作者:TORBJORN LAEDRE
原文:http://blogs.unity3d.com/2015/05/28/unique-character-shadows-in-the-blacksmith/


那是一個風光明媚的早上。我想應該是去年秋天的某個時候,我們終於等到了引頸期盼的消息:維京挑戰者角色終於來了!

當時它仍是一個粗模:一個光頭,
尚未賦予任何材質沒有任何皮膚貼圖,但我們為他的到來感到興奮無比。 「快來人啊,把給這壞小子給我打上材質,然後放進我們的場景吧!」

完成後,它確實看起來非常酷。除了……有些地方看起來怪怪的。

「呃,這傢伙真的有接收動態陰影嗎?」

事實上他真的有接收動態陰影,然而並非以我們期望的結果。

總體看來角色並沒有收到任何影子,因此我們斷定問題就出在陰影上,它看起來很奇怪,而且影子參差不齊。

問題所在


我們快速的對著色器(shader)進行了研究之後,醜陋的真相就原形畢露:不但一半的角色沒有陰影,而且這角色陰影看起來有種塊狀的詭異感。


「為什麼會這樣呢?」
你可能感到好奇。不管怎說,Unity5不是採用了全新的陰影演算法嗎?

確實如此,而且的確很強大。

我們的場景最遠有3000M的距離,而且我們想要從很遠投射陰影到視椎的每一個像素上。現在,我們當然竭盡所能地調整了級聯分裂(
cascade splits)和陰影偏移(shadows biases),讓近距離或是離鏡頭非常非常遠,效果看起來都很不錯。

然而,到目前為止,我們卻從未經歷過一種情況,那就是在一個如此宏大的場景中放一個離相機很近卻又很複雜的角色。

問題出在我們缺乏用在角色身上的陰影解析度,為確保場景美觀深度偏移過大,導致它將陰影偏移角色的一半身體。

我們才了解,一塊皮帶在距離它1cm的盔甲上投射出陰影,和一塊中等尺寸的岩石在地面上投射出陰影完全是兩回事。

又有誰能料到呢,嗯?
因此我們需要尋求一個解決方案來解決這困境。我們可以將Quality Setting裡陰影級聯(Shadow Cascades)的第一級移動到非常非常靠近相機的位置,但代價就是這場景浪費了一級可用。

它僅僅會在我們的角色們真的非常非常靠近相機時才會運作,但已經足夠解決我們眼下遇到的問題了。

解決方案


然而,我們決定用一種比較老派的技術解決於這個問題。

「如果我們針對角色另外渲染一層陰影貼圖呢?」試試看。

寫了兩百行程式碼後,結果出現了:


此時,我們已經能夠產生足夠多的數據來呈現任何可能的陰影了。但時間不允許我們花太多時間去做最佳化微調,我們決定做一個類似於Nvidia光導開關[註1]的一個距離感知取樣方案。

我們還設有一個選項用來捕捉人物對焦領域之外的陰影投射數據,
這裡就沒抓圖了。比如說,我們仍然需要有靜態的世界的陰影透射到這些動態的角色上。

這類投影被會被投到陰影渲染鏡頭最近平面上,確保他們在陰影濾波方案中總是具有最大的攔截與接收距離 。

如此一來,剩餘的唯一的問題便是如何將上述工作整合到渲染管線(rendering pipeline)了。

在研究過後,結果我們發現原來有一個非常簡單的方法來對常見的Unity shader陰影方法進行重寫。

經過幾次改良,我們簡化為只需添加兩行額外的程式就可以對著色器加上這種陰影:

#pragma multi_compile _ UNIQUE_SHADOW UNIQUE_SHADOW_LIGHT_COOKIE
#include "UniqueShadow_ShadowSample.cginc"

請注意,為確保能夠正常運作,這裡的「include」部分必須寫在其他的engine includes之前。

因為我們在這裡用了一個include文件來將真正的複雜部分給覆蓋了。
為了避免誤導,若有人想要做類似的事情,這裡本質上可以歸結為:

#if SOME_CONDITION_ENABLING_OUR_FEATURE
#include "AutoLight.cginc"
#undef SHADOW_COORDS
#undef TRANSFER_SHADOW
#undef SHADOW_ATTENUATION
#define SHADOW_COORDS(i) SOME_OTHER_COORD(i)
#define TRANSFER_SHADOW SOME_OTHER_TRANSFER
#define SHADOW_ATTENUATION(i) SOME_OTHER_ATTEN(i)
#endif


這裡的條件判斷決定了是否啓用這種獨特的陰影,以及我們目前是否正在呈現一個定向光。

而第二個條件判斷則決定了能否與其他類型的投影光源和平共處。

成果!



在經歷了所有艱苦的工作之後,我們究竟獲得怎樣的結果呢?下面就是同一個場景下打開和關閉這種「獨特陰影」技術時,所呈現出來的場面。

老派技術最終得分獲勝!

總結



有一點需要注意的是,如同像絕大多數其他的渲染功能一樣,增加陰影貼圖到場景是有代價的。

陰影貼圖會佔用更多的顯卡記憶體,而且渲染會產生額外的draw call,同時這種方式也增加了著色器對於頻寬使用和運算性能的需求。

在The Blacksmith中,我們對系統進行了設定,使得我們能夠根據角色和相機的距離來決定這種獨特的陰影技術是否被啓用。因此,我們只在那些人物佔據畫面大部分的鏡頭中才會啟用這功能付出額外的渲染成本。

對於一個普通的遊戲而言,在玩家正常遊戲的過程中可能永遠不會出現角色如此靠近相機的情況,我想可能只有在特定的過場動畫時,才需要啓用這種技術。

為了更好地展示這一功能,我們已經把它抽離到了一個小的專案,你可以從Asset Store下載它。

這專案包含了一個基本場景,用來模擬一些在大場景裡距離相機非常近的角色細節。

即使第一級層陰影級聯覆蓋僅1%的陰影距離,在左側運用了這「特殊陰影技術」和右側用了一般級聯陰影技術的維京挑戰者之間,依然存在著顯著的差異。


參考資料:
[註1] 英文

沒有留言:

張貼留言

關於我自己

我的相片
Unity台灣官方部落格 請上Facebook搜尋Unity Taiwan取得Unity中文的最新資訊