Unite 2018 | 《崩壞3》:在Unity中實現高品質的卡通渲染(上)


http://forum.china.unity3d.com/thread-32271-1-1.html

 

我們已經發布了Unite 2018 江毅冰的《發條樂師》、Hit-Point的《旅行青蛙》、育碧《Eagle Flight》演講分享,不少開發者在后台留言希望小編盡快分享米哈游技術總監賀甲《崩壞3》的案例分享,因為這場是干貨滿滿的爆場。我們非常感謝米哈游以及賀甲長期以來對Unite大會的支持,由於篇幅限制,本次演講內容將拆分成上下二篇。



下面為演講內容:

大家好,歡迎來到Unite2018參加我們這次演講。簡單做一下自我介紹,我叫賀甲,目前在米哈游擔任技術總監。我和我的團隊主要關注在PBR和NPR方面的實時渲染,以及用於動畫CG和游戲的過程動畫和交互式物理的研究。目前,我們的一部分工作是利用Unity實現高品質的卡通渲染。

這次演講的主題是《在Unity上實現高品質卡通渲染的效果》,這些方法的實現針對各個平台的特性進行了優化,涵蓋了從移動端,到高性能PC等不同等級的平台。



我們先來簡要介紹一下本次演講涉及到的主要方面。首先會介紹一些應用在移動端有關《崩壞3》的渲染特性。然后我會談談動畫風格CG渲染中使用的一些技術,例如:插畫風格的角色渲染、特殊材質的渲染、特效的渲染及與卡通渲染適配的后期處理等。最后一部分是關於一些雜項和對今后實現的一些展望。



首先,我們來看看在《崩壞3》的場景中使用的一些渲染特性。

從下圖中我們可以看出,場景中使用了不少特效來提升表現力。例如:bloom后處理效果、動態粒子、平面反射、屏幕扭曲特效等。下面我們將會逐一對這些效果進行解析。



下面展示了這些動態特效。



我們來看一下如何實現高品質的反射效果。

在移動端實現高品質的反射,平面反射是一個綜合了效果和性能因素較好的辦法。通常做法是以地面為對稱平面,將攝像機放置在對稱位置后渲染場景得到反射結果。

為了能表現出地面的金屬質感,首先我們對反射結果應用六邊形采樣模糊,然后使用金屬紋理細節法線貼圖來擾動反射結果,除此之外我們還使用了鏡面反射貼圖和菲涅爾效果來進一步增強反射質感。在一些遠離地面高度或非水平的次要反射表面上,平面反射就不在適用,為此我們使用環境貼圖反射作為替代方案。

為了盡量減少渲染反射場景所占用的開銷,我們將反射分辨率限制在1/3以下,由於反射貼圖會經過模糊處理, 即使降低了較多的分辨率也並不能明顯看出區別,並且我們在渲染反射的過程中還使用簡化版的材質,並忽略一些不是很重要的小物體。



接下來讓我們看看另一個效果:全屏扭曲特效的應用。

我們在《崩壞3》的場景中較多的使用了屏幕扭曲效果,比如:刀劍的拖尾特效,時空斷裂效果,水流瀑布及其它場景效果。

在渲染扭曲效果的過程中,我們使用3個通道來存儲扭曲的渲染結果,2個用於存儲UV偏移,另一個用於存儲扭曲強度Mask,扭曲強度Mask用於執行深度剪裁和基於距離的強度控制。

使用單獨的Pass渲染扭曲結果到幀緩沖紋理對於移動平台來說開銷較大,所以我們在最終的后處理中整合應用了扭曲效果,相比前者要快很多。 但這種方法也可能導致靠前面的物體由於沒有分層處理而混入后面扭曲材質的問題,不過考慮到移動平台的性能限制,相對於整體效果而言這種妥協是值得的。



接下來讓我們看看bloom的實現,整個場景如果開啟HDR會使用 fp16格式的Render target,然后下采樣到原始大小的1/4大小以便之后的后處理流程使用。

首先,我們需要指定一個亮度閾值來提取圖像中的高亮區域,實現方法也並不復雜,只需從源像素減去閾值,得到的結構就是提取后的高亮度區域,疊加這層內容能使結果看起來更具對比並且色彩鮮艷。接下來,我們產生4個大小依次遞半的Render target,並將其內容應用半徑逐漸增大的高斯模糊。最后我們將這些模糊后的結果合並起來,以獲得最終的bloom效果。

從下面最終的效果圖我們可以看到,bloom效果不僅起到用來表達高亮區域的視覺效果,還對整個圖像的色彩中起着明顯的潤色作用。



當完成了反射渲染,扭曲效果的及bloom 的處理后,最終就可以將這些中間結果合成在一起。我們使用filmic tone mapping與曝光和對比度控制來將fp16 HDR的原圖像轉換為最終的LDR幀緩沖。由於這些合成操作都是在一個Pass中完成的,所以即使在移動設備上也可以滿足性能方面的需求。



下面我們來介紹一下游戲中的天氣和雲海的實現。

我們想要創造一個能讓玩家感受到縱深,具有各種豐富形態以及動態光照變化的雲的渲染系統。而該系統也應該易於調整和使用,方便美術可以創造出不同類型的雲層效果。這對我們來說也是一個有趣的挑戰,接下來就讓我們來談談這些功能。



首先讓我們看看渲染雲所需要的資源,因為我們想要實現可以24小時動態變化的風格化雲的光照效果,如果直接存儲畫好的貼圖數量就會太大而且不方便調整,所以我們使用多層着色來實現這一點。

我們使用4個通道來表示雲的光照及陰影:基礎照明層,陰影1層,陰影2層,和邊緣光層,通過為每個圖層設置不同的顏色,我們就可以獲得不同時刻的雲的色彩方案。我們一共准備了8種形狀不同的雲的模板,用來構建各種不同的雲海景觀。



為了構建雲海景觀,我們使用了很多朝向屏幕發射雲朵的粒子發射器,並且使用不同的雲的模板以及發射模式來組合出不同的雲海景觀,我們實現了各種類型的雲海以及暴風雨天氣等,這些預設都保存在天氣配置中。此外我們還使用關鍵幀來定義天空背景和雲彩的顏色。隨着時間的流逝,雲的色彩就根據關鍵幀來變化。

在性能方面主要的開銷是Overdraw問題,如果我們按照固定控制的Pattern來發射雲雖然可以以最小的Overdraw來獲得較好的雲海密度,但可能會看起來較為重復,加入產生位置的隨機因素可以解決這個問題,但要想獲得看起來不那么稀疏的雲海效果就需要相比固定Pattern更多的粒子數量,我們對於粒子發射配置都有細致的參數可以調整,以便在二者之間可以找到較好的權衡點。



這是一個24小時晝夜變化的雲海景觀。



這是另一種雲海景觀的晝夜變化。



這是暴風雲閃電的場景。



現在讓我們來看看游戲場景中使用的天氣系統。

我們主要通過全局霧效,Skybox顏色和方向光的設置來改變場景的天氣和氛圍。對於霧效同樣有許多參數可以調整。我們給霧效基於深度划分為遠近距離二個區間,遠近區間都可以設置不同的顏色和強度值來創造各種各樣的氣氛。Skybox也可以控制天空顏色漸變,雲的受光及陰影顏色等。綜合上述調整選項,我們就可以創建 晴天,雨天和大霧,多雲和夜間等天氣。

另外人物的光照也會受環境的影響,主要的光照顏色由方向光決定,局部區的陰影的變化,比如:角色走進陰影區域,由一些從關卡編輯器中手工放置的Lighting volume定義。



讓我們再來看看游戲中使用景深的情況。

移動游戲中使用景深一般並不常見,因為常見的景深實現對於移動平台來講還是開銷較大,我們主要在人物選擇界面和任務簡報會話中使用景深效果來突出表現人物。

由於這些場景不需要景深的過度,我們使用一種特殊的方法來進提高移動性能。不使用depth buffer做COC混合,而是使用單獨的相機直接繪制背景圖層。在應用模糊通過后,通過將背景和前景人物組合在一起來獲得最終圖像。

為了得到更好的視覺效果,我們使用六邊形采樣模式來獲得更好的bokeh形狀。除此之外還有bokeh強度調整參數,以使其看起來更清晰,我們使用亮度值作為增量因子,2通常是一個合適的值。

性能方面為了保持性能的穩定,我們模糊背景的分辨率視模糊程度而定,更大的模糊尺寸使用更低的分辨率並且更不容易察覺,我們還使用Unity內置的曲線來描述它們之間的轉換關系。



下圖展示了動態調整模糊大小和焦散強度的結果。



在游戲場景中,我們還實現了一個看起來挺酷的效果,當給最后一個敵人致命一擊的時候就會激發子彈時間,這時所有高速運動的物體都會慢下來,在下雨天我們就可以明確的看到雨滴的形狀。

為了實現這個效果,我們使用了4個代表雨滴不同速度下形態的關鍵幀,再根據時間快慢尺度對其進行垂直拉伸。 在正常的時間尺度下,雨滴看起來像一條直線,在時間變慢的時候逐漸縮短變成雨滴形狀。在這里我們同樣使用了動畫曲線來控制拉伸,關鍵幀選擇和時間快慢的關系,調整起來非常靈活方便。



剛才我們談到的都是一些針對移動端優化的渲染功能,下面我們來介紹一下用於動畫風格real-time CG或次世代游戲的渲染方法。

在過去的二年中,我們陸續制作了二個短視頻,其中體現了我們的新渲染風格。(B站視頻地址:https://www.bilibili.com/video/av14260225)



我們將它發布在了B站上,3天內獲得了B站全站月榜排行第一的位置,至今已有超過300萬的點擊量。(B站視頻地址:https://www.bilibili.com/video/av7244731)



下面我們就來談談這些視頻中應用到的一些實時渲染CG技術。

首先我們來看看角色的渲染,我們的目標是實現完全動態的光照和陰影,所有材質都對各種光照現象做出正確的反應,包括主光源和區域環境光。這就要求我們不能使用任何在紋理上畫死的光照表現。


用於角色渲染的主要特性有:多通道Ramp的材質Shading方法,眼睛,頭發和其它各向異性材料等特殊材料的處理,以及PCSS角色軟陰影和高品質的勾線。



首先我們來看一下多通道Ramp的Shading方法。

我們希望角色的陰影和顏色的變化可以表現出更細膩的插畫風格,所以我們使用2D ramp紋理來表示這些細微的變化,其中RGB通道分辨用於描述於不同陰影層的漫射陰影范圍。每個層都可以制定不同的顏色,這樣就能在明暗變化中做到精細的色彩變化控制。

對於卡通風格的畫面,如果上色只是純明暗變化,陰影處就會顯得比較臟,缺乏表現力,而如果提升暗處的飽和度和色相變化,整體色彩看起來就會比較鮮活。而且通過調整垂直紋理采樣坐標,我們可以實現動態的軟硬風格轉換。 從另一角度來看這種方法還間接表現了皮膚的次表面散射效果。



下面四幅圖展示了多通道逐層上色疊加的效果。 大家可以看到通過一層層的上色疊加,皮膚層次細節會變得更加豐富。



上下二副圖分別展示了采樣不同位置的ramp texture所對應的渲染效果,不同的ramp可以獲得各種不同的上色風格。使用hard ramp比較接近Cel-shading,soft ramp則是類似與插畫柔和的陰影層次變化。

由於我們使用了2D的ramp紋理,它們之間的變化是可以動態調整的,我們可以使用ramp mask紋理來選擇每像素的ramp軟硬以實現插畫的手繪風格。這個ramp mask紋理可以由美術直接在模型上進行繪制。我們在Unity下有一個3D paint工具,使用起來較為直觀。



插畫風格渲染的另一個重要因素是使用紋理筆觸。我們可以使用不同的筆觸紋理圖案以獲得不同的着色風格。對於每個筆刷紋理,我們有4個通道可以存儲代表不同方向的筆刷圖案,混合使用這些筆刷可以獲得更豐富的筆刷變化。右邊的二張對比圖中,使用筆觸紋理的有着更多手繪的感覺。



下圖顯示了應用了帶有筆觸風格的皮膚材質對不同光照角度的渲染結果。



接下來讓我們看看如何實現高質量的邊緣光。

同樣是基於菲涅爾方法,我們有參數來控制它,比如:邊緣寬度和平滑度;除了這些全局控制參數之外,我們也使用筆刷紋理來增加一些局部變化。我們定義邊緣光既可以來自於方向光源也可以來自於環境貼圖,使用方向光我們可以按需求定義邊緣光,使用環境貼圖,我們可以根據環境光照來獲得邊緣光以顯得更真實,二者都比較有用,可以結合使用。

為避免邊邊緣光出現在不需要的區域,我們使用AO紋理和shadowmap來頻閉掉遮擋區域。我們可以看到,對比圖中左邊帶有邊緣光的形狀顯得效果更突出。



卡通風格對於面部一般不會有太多陰影層次的變化,如果我們直接套用之前的ramp方法應用在臉部,效果就會像右側的圖看起來一樣不自然,為了改善這種情況我們使用頂點色的一個通道作為mask來控制臉部的上色層的強弱,通過壓低漫反射表現來達到想要的卡通效果。



接下來我們來說一下高質量角色軟陰影的實現。

如果我們直接使用Unity內置的CSM陰影,在鏡頭靠近角色的時候陰影品質並不能滿足需求,所以我們就為角色單獨渲染了一張shadowmap,以確保恆定的陰影品質。為此我們還實現了基於視錐的shadowmap,根據角色的boundingbox和視錐求交集部分,以此作為渲染區域。就可以最大化陰影貼圖的使用率,

此外還使用了Variance shadow map以及PCSS來減少陰影瑕疵以及獲得自然的軟陰影效果。另外,如果要實現正確的透明材質陰影,還需要額外的通道根據材質的透明度來存儲陰影強度。我們可以從實例圖片中看到半透明的裙子可以投射出自然的陰影。



眼睛的處理我們使用了基於物理的折射計算。普通卡通模型處理眼部的做法通常是把眼白留空,瞳孔凹陷下去,這樣在側面的時候也不會鼓出來顯得比較自然,然而如果要做眼部近距離特寫,這種做法看上去就不能令人信服。使用真實折射算法,眼球本身還是按照球面來做,然后根據視線角度算出折射系數去偏移查找貼圖對應點 。

下面對比圖顯示了有無折射的實際效果, 我們可以看到,如果沒有折射效果,眼部側面看上去較為奇怪。



此外我們還加入了光線折射后的焦散光效果,使得眼睛的質感得到進一步增強。對於非寫實風格渲染,物理正確並不是要考慮的因素,由於卡通渲染的特殊情況,我們希望的焦散效果出現在入射光線的另一側,並且入射角度越平行看起來越明顯。

實現方法是通過入射光和眼球前向的夾角算出入射光強度,這里我們使用inverse diffuse來模擬,再輔助fresnel公式做亮度變化,最后乘上eye caustic紋理得到最終效果。

通過下面對比圖我們可以看到如果沒有焦散效果眼睛就顯得暗淡無光缺乏質感。



下圖展示了眼睛的折射以及頭發的各向異性高光效果。



由於篇幅限制,上篇的內容就先分享到這里,明天我們將繼續本次演講內容,分享發色渲染、光照、后期特效處理等一系列內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM