Unity學習筆記 Vol.81 如何制作卡通著色器
摘要
????本次我們將了解Unity開放項目中卡通風格背后的理念和流程。開放項目是小型開源游戲,社區(qū)創(chuàng)作者可自由合作,為整個游戲開發(fā)做出積極貢獻。這個項目是動作冒險游戲,你可以在描述中找到GitHub及相關(guān)鏈接。
????我們使用了Unity 2019.4LTS開發(fā)游戲,確保開發(fā)過程中有最佳的穩(wěn)定性。我們更新了卡通著色器,使其兼容Unity2020.2,你可以在原Git代碼庫的一個分支中找到2020.2版本的卡通著色器,名為devlog-1-toon-shading。項目下載請參考官方視頻教程。

教程
確定卡通形象
????在確定了藝術(shù)風格后,我們很清楚哪個Unity可編程渲染管線最符合我們的需求,圖像風格并不寫實,不需要高度逼真的視覺效果,我們需要的是干凈、簡單且風格化的圖像風格,因此決定采用通用渲染管線。

????在這個渲染管線下,我們可以實現(xiàn)卡通風格,同時保證Unity項目性能,在各種硬件上運行,著色器使用Shader Graph制作有兩個主要原因,我們希望這些內(nèi)容對于大家來說都是可以使用、理解的,第二個是使用Shader Graph制作出畫面后,我們可以輕松為著色器添加額外的效果,比如使用頂點偏移的風吹效果,調(diào)整透明度實現(xiàn)的溶解效果等等


???卡通著色也稱為Cel Shading,是一種以非真實光照模型為特征的渲染風格,此類風格通過用統(tǒng)一的顏色表示陰影和高光區(qū)域,并不使用普通的漸變著色,除了自定義的光照,我們還用一個額外的通道來制作黑色的輪廓線,為模型添加更多細節(jié),使其看起來更像會動的漫畫或手繪動畫。

????我們僅在人物身上添加了輪廓線,使其從環(huán)境中脫穎而出,可以看到,最終3D模型與原畫非常相似,為了取得最終結(jié)果,我們將加入各種類型的光照,并可以從Shader Graph中控制光線。

????在此階段,我們沒有專注于卡通著色效果,相反,我們希望先確保著色器支持以下內(nèi)容:
· 帶有光照、陰影和鏡面反射的自定義光照模型
· Shadow cascades(陰影級聯(lián))
· 靜態(tài)對象的烘焙式全局光照
· 環(huán)境光
· 其它光照與陰影
· 光照探針

????第一步是添加主光源支持,默認下,URP中的主光源是場景中最強的方向光,借助Shader Graph中的自定義功能節(jié)點,我們可以收集這個光源中的所有光照信息

????節(jié)點中的代碼會調(diào)用URP中已有的一個函數(shù),稱為GetMainLight,用以訪問相關(guān)數(shù)據(jù),如方向、顏色和陰影貼圖,在這里作為陰影衰減(ShadowAttenuation)顯示出來

????接著取幾何表面法線向量和光方向的點積來建立自定義光照模型,我們將結(jié)果鉗制在0和1之間,再與陰影衰減相乘

????結(jié)合數(shù)值結(jié)果和光照顏色,就形成了基本的漫反射光

????除了從主光源獲取數(shù)據(jù)輸入之外,我們希望著色器能接收,場景中存在的所有其他光照

????因此也和之前一樣使用了自定義函數(shù),借助GetAdditionalLight內(nèi)置函數(shù),可以遍歷所有其他存在的光照,再使用GetAdditionalLight來收集每種光照數(shù)據(jù),這時事情開始有意思起來了

????如果仔細觀察著色器,會注意到MainShadowAttenuation,也用在了靜態(tài)幾何形上,以實現(xiàn)對大型幾何陰影的實時控制,我們建立的方法基本等于Unity中的混合光照模式

????該實時陰影將乘上Baked GI節(jié)點的輸出,取得最終的陰影數(shù)據(jù)

????接著角色便能在卡通風格的景色上投射黑色陰影,符合原畫。Baked GI節(jié)點也為著色器添加了光照探針支持,適用于動態(tài)幾何形

????為了測試著色器的功能,我們創(chuàng)建了一個包含所有光照情況的場景,加入了方向光、實時點光源,混合點光源,以及靜態(tài)與非靜態(tài)球體,兩者會投射出實時與烘焙陰影,在該著色器基礎(chǔ)上,我們就能制作卡通著色器效果了,著色器上的所有光照功能都根據(jù)運行邏輯進行了劃分,我們可在節(jié)點之間添加額外的節(jié)點上步驟來控制數(shù)值實現(xiàn)想要的畫面,卡通著色器一個覺特征是,用高對比度的色帶取代平滑的顏色漸變,使用稱為Ramp Shading的技術(shù)

????為此,我們添加了一些漸變色采樣節(jié)點,將所有的光照數(shù)據(jù)轉(zhuǎn)換為由自定義色帶定義的新顏色

????我們的設(shè)想是將表面光照的梯度值限定為較小范圍內(nèi)的顏色,這樣一來就能在受光與陰影部分生成清晰的分界線,通過修改色帶顏色可以實現(xiàn)不同的畫風。
渲染輪廓線

? ? 要制作輪廓線效果,我們需要從攝像機緩存處,獲取法線與深度信息,需要使用結(jié)合了兩者的紋理,這種紋理直到最近才引入URP,主要用于屏幕空間環(huán)境光遮蔽,但它并不支持兼容2019.4的URP,幸好URP是可編程的渲染管線,可以根據(jù)需要修改,實際上我們采用了網(wǎng)上一個質(zhì)量較高的方案,作者是技術(shù)美術(shù)Alexander Ameye,

????為了生成法線與深度紋理,我們創(chuàng)建了一個自定義可編程渲染功能,將其添加到了渲染器資源中

????生成新紋理后。再使用自定義功能節(jié)點,從紋理中采樣、收集法線與深夜數(shù)據(jù),使用這兩種數(shù)值繪制輪廓線。我們可以為每個材質(zhì)修改輪廓線的寬度,深度和法線敏感度,定義不同幾何形上輪廓繪制的方式、位置,更好地匹配形狀。

????最后,我們將輪廓繪制邏輯加入了卡通著色器,將輪廓值乘上卡通著色器模型的顏色,得到最終數(shù)據(jù)實現(xiàn)最終結(jié)果,之前提到,該著色器為Open Project的早期內(nèi)容之一,隨著項目的推進,我們會根據(jù)游戲需求的變動不斷增補,修改著色器,在了解了著色器背后的制作流程后,我們再來談?wù)勴椖康南乱徊?,以及如何解決當前面對的挑戰(zhàn)。其中有一個制作中的改進,是關(guān)于對象移動時陰影出現(xiàn)的抖動現(xiàn)象,該問題不影響自身所帶的陰影,僅影響其他物體投射的陰影,由陰影貼圖突兀的顏色過渡直接造成,因為貼圖的灰度值都被近似取為黑色或白色

????增加陰影貼圖的分辨率,可減少抖動現(xiàn)象,但這不是理想的解決方案,一個減輕問題影響的快捷方案是用Toon Ramp卡通色帶,而不是強制轉(zhuǎn)變的顏色渲染陰影,在色帶中加入一塊緩沖區(qū),光照值可以流暢地從黑色變?yōu)榘咨?,不會在兩個數(shù)值之間跳動。

????另一個可能加入的功能是處理著色器顏色屬性的上色系統(tǒng),根據(jù)環(huán)境在不同的色板間切換。比如,在夜間用藍色色帶為著色器的對象上色,或使用橙色到紫色的色帶來模擬夕陽,修改色帶的深色,便可將陰影的顏色改為任意顏色,而在輪廓線上,我們需要解決低分辨率下出現(xiàn)的線條鋸齒現(xiàn)象。