前言:
成果:
文章一樣放在
個人網站,歡迎光臨小寒舍。 耶嘿 >wO ((溫迪臉
上一篇有簡單講到我對Outline Shader效果之心得:做法能分為基於Image Effect的邊緣檢測 or 基於物件個體的邊緣檢測。然而前者效果不如預期、粗細也不好控制,所以本篇主要講解後者。
(左Image Effect、右Unlit Shader)
基於深度之卡通渲染
第一個問題便是各個物件本身如何自己做邊緣檢測? 要用甚麼資訊做檢測? Image Effect是對整張camera貼圖做卷積,而各個物件的texture又牽扯到uv的問題。 因此本專案使用物件像素座標去採樣camera的深度貼圖,對深度做卷積。
(雖然不明顯,但還是能看出深度差別)
ComputeScreenPos其實只有對x,y做處理,z,w同輸入值,因此這個"screenPos"還需要除以w投影至3D空間。
雖然理論上clip space的XYZ值域範圍介於[-1,1],但實際上是介於[-w, w] (各平台可能不同),-w是near plane、+w是far plane。 (在正交鏡頭下w為1)
對深度圖做卷積
這邊先使用簡單的Sobel核,不同核算出來的效果不同,例如之前在學影像課的時候發現Kirsch核抓到的邊緣比較細、多(?)。
把上一小節的概念擴充成計算周遭九宮格像素之screen pos,以採樣深度圖。
顏色漸層
用
半蘭伯特光罩模型計算陰影程度,然後映射到漸層貼圖,若要採樣整張UV的值域可以選擇用全蘭伯特。
關於加入高光(specular)的作法可以回去複習一下
之前的文章喔,(偷懶~)
2D Outline變體
感謝小呈之前的文章[1]介紹Shader分支的幾種做法: if/else的動態分支會破壞GPU的並行性,若數量可控的話可以選擇在編譯時產生Shader變體的靜態分支作法。
由於本專案的遊戲是2D、3D物件混合使用,雖然是2D平面,但我希望能使用outline、bumpMap、高光貼圖等效果,因此與其再複製一個腳本改成2D,不如讓"2D"變成一個選項。
能有效調整粗細。
定義CUTOUT參數控制是否使用2D的計算方式。平面物件深度都一樣,因此不能用深度卷積的結果判斷outline,於是我採用alpha值做卷積。
可以在漸層對應的貼圖做光暈的效果,不然目前我上面測試用的漸層貼圖只有0跟淡藍色兩種。