我愛圖學!我愛圖學!
參考資料
【密技】教你做出香香的 One last kiss 專輯風濾鏡
之前在場外看到這篇文後我其實就想做了,但備審卡著我沒空研究。剛好備審寄完,專案堆的東西也清完一部分了,趁有一點點空閒,來研究被我放置了兩個月的 Shader。
專案原始碼和其他補充參考附在最下面。哭阿結果這篇也沒辦法加進備審了,希望審特選的教授會來翻我小屋QAQ
流量轟炸警告,照慣例先上成果~
(gif 會太大,所以我還是放影片
)
我用了兩種方式來實現這個效果。第一是
邊緣檢測,用卷積矩陣做判斷,透過周圍像素的顏色、深度、方向差距來判斷物體邊緣,花了快半天;第二種則是參考資料中
的線稿提取,透過清除色調和色塊膨脹的方式提取出線條,花幾個小時搞懂文章說到的那些濾鏡原理就成功了,而且 code 和邊緣檢測相比短超多的
其實我原本只打算做邊緣檢測的,因為我以為線稿提取只有賽路路的畫風會有效,但事實上任何圖像都行,然後複雜度和計算成本更低...效果也更好看。
不廢話,來解說原理和算法吧~
邊緣檢測 Edge Detection去年我就有研究過邊緣檢測的算法了,但那時還沒完全懂。ㄅ過這一年花不少時間慢慢消化後總算弄清楚原理了。透過一個 3x3 的九宮格卷積矩陣 (Kernel Convolution) 進行計算,每個格子都有各自的權重,強度根據要計算的目標做調整。
邊緣檢測的 Kernel 叫做索伯算子 (Sobel operator),水平的檢測長這樣,垂直的就是轉 90 度。
把原始圖片輸入進去,產生色差的部份就是不同色塊的邊緣。
單純色差產生的邊緣還不夠,有些相同顏色的交界會檢測不出來,所以我也用 Depth Buffer 的深度差和 Normal Buffer 法線方向差距檢測邊緣。
深度差就是相鄰像素的深度相減,基本上會產生生度差距就代表一定是物體邊緣。
方向差距就是和相鄰的像素法線做內積投影的結果數值。
因為各自算法的結果有些差異,所以最後要再把三種數值乘上權重,並用 Pow 把多餘的噪點線條抹除,完成混和的邊緣檢測。
做到這裡就完成線條的部份了,接下來就是漸層上色,為了不搞太複雜我就用兩種顏色的插值而已。基本上就是把畫面 uv 當插值參考,如果要旋轉的話,弄出一個旋轉角度的向量,把 UV 投影上去就行了,拿投影結果當插值權重。
接著就把漸層顏色混上線條,剩下部份填上背景顏色。不過單純拿白色當背景有點刺眼,所以我去素材庫找了一張紙質的 Texture 當作背景,也提昇一點畫面質感。
邊緣檢測的成果
線稿提取 Line Capture依照參考資料中的作法提取出現條,稱呼成線稿提取主要是我查資料的時候,其他人也是這樣叫的,所以就這樣吧
首先是去除飽和度和負片效果。去飽和,就是把畫面轉成灰階的意思,可以直接 RGB 值相加除三,至於負片就是 1 - RGB。
加亮顏色
參考教學中有這一步驟,但因為計算方法有些不同,在這裡沒有效我就跳過了。
濾鏡最小值
我花最多時間研究的步驟,這個濾鏡的效果是取周圍像素中的最小數值,會產生類似塗抹的效果,
並讓色塊稍微膨脹。
然後!下一步是重點,處理過程主要就是從這步驟取出線條的,但因為 PS 裡濾鏡效果會自動運算的關係,所以我花了一點時間思考過程中發生的事。因為濾鏡本身的過濾算法,加上最小值的膨脹效果,如果用濾鏡把膨脹後的圖過濾掉原始圖片的話,就會剩下多餘膨脹出來的部份,取得線條。
而實現方式就只需要直接相減而已,搭拉~
但因為兩個值還是很接近,所以減出來的線條強度會很弱,要再另外乘上增強強度。
然後就是上色!
成果
沒有 PhotoShop 怎麼辦?自己寫一個畫面處理重現就好了 :P
最終結果我覺得比起一開始的邊緣檢測,線稿提取大勝,不只程式短很多,效果也更勝一籌。
邊緣檢測的線條太粗了,而且過程中產生的噪點線條很難看,用 pow 稀釋掉結果又讓線條感覺太銳利。
但線稿提取就沒這問題,透過色塊膨脹的方法取得線條,再用乘的增強強度,造點在遠處還產生意料之外的效果,不需要多修正。老實說我做到最後才想通原理,最小值那裡查不少資料才搞懂,之前完全沒想到能用這種方始提取線條,學到了學到了。
就醬,能量又回復了不少,感謝偉大的計算機圖形學
原始檔我上傳到這裡,對 code 有興趣或想自己在編輯器裡走走都可以載來玩,然後我把 FPS Controller 寫的好一點了,不然上次那個手感真的有夠糟www
https://github.com/angus945/One-last-kiss-style-Rendering
參考資料
卷積矩陣原理解說
https://www.youtube.com/watch?v=C_zFhWdM4ic
補充資料
晚安~