創作內容

6 GP

Shader初學筆記2——光照基礎

作者:pudding│2020-04-17 14:54:49│巴幣:1,010│人氣:826
在上回聊完了一些對Shader的初步了解後,這次就讓我們來看看Shader的光照基礎吧!

現實中的光照極其複雜,要完全地在遊戲中呈現並不容易,所以我們通常會改用一些比較接近的模型(我自己的解讀,這裡指的模型代表著整理好的一套公式),今天我們要來看的便是其中一個常用的模型——Phong lighting。

Phong lighting大致可拆成三個部分來看:
-ambient(環境光)
-diffuse(漫射光)
-specular(高光)
接下來我們將一一了解這三個部分的特性。

ambient(環境光)
ambient算是三者之中最簡單的一個,它所代表的是很弱的光源產生的光,均勻地照在整個物體表面上。
具體上的寫法也相當簡單,讓我們先在Unity當中建立一個新的Shader吧。

(基本上內容是接著上回的基礎Shader增加,不過這裡還是新創了一個Phong Lighting)
首先我們要先在屬性欄位增加兩個變數,_AmbientClr和_AmbientStrength,同時也要在Pass當中再次宣告我們要取用的變數。
接著我們會在Fragment Shader要輸出前對原本的顏色進行調整。
(依照環境光強度將色彩混和上去)
寫完後的效果
我們可以稍微調整

diffuse(漫射光)
接著讓我們看到第二個部分,diffuse所代表的是一個較明顯的光源打在物體表面上的效果,物體的背面會比較暗,而正面被照到的部分則會比較亮,在這裡的話我們選擇使用場景內的平行光(Directional light),有點像是遊戲世界中的太陽光 (聽起來像某種政治宣傳)。

首先我們來取得平行光源(我有時候會稱其為世界光源)
_WorldSpaceLightPos0是Unity官方提供內建變數(資料),在後面補上".xyz"是因為我們只有要取用其中的前三個向量值(他原本的格式為float4,四維向量)
另外也要注意一點,_WorldSpaceLightPos0給你的是"物體看向光源"的單位向量(長度為1),而非光源打在物體上的向量。

那麼在取得光源的向量後我們接著就該來計算光打在物體上的強度了,這裡我們會需要取得物體身上的法線向量(Normal Vector,也就是垂直於物體表面上的向量)。
圖源

我們要利用物體表面的法向量來計算光照強度,因為越是面向光源的部分,其法向量與看往光源的方向就越接近。

為此我們先試著取得物體頂點的法向量。

記得要在Vertex Shader那邊做初始化,將資料存起來


最後則是在Fragment Shader裡面去做運算,這裡順便提一下平時檢測Shader的一個方法。
我們可以直接先把我們想確認的數值渲染出來,以上圖為例的話我們會看到這個結果。

多彩繽紛的球球~
好啦,這些顏色代表什麼呢?首先最基本的我們要瞭解說球體最右邊的法向量就是直接正對著右方(向量數值1,0,0),依此類推,正上方0,1,0,後方則是0,0,1。
然後我們可以注意到它三邊的顏色基本上跟右上角XYZ軸方向一樣(只要你沒有特別去轉動球體物件的話),這是因為顏色資料的RGBA值的前三項正好對到了座標系統中的XYZ軸……我承認這講起來有點廢話><,不過如果你像我一樣很健忘的話,你可以隨時利用右上角的坐標軸去辨認。

說完了檢測Shader的方法後,讓我們把重點拉回到diffuse光照上吧,先讓我們看看它完整的計算方法。
(記得如果想獲得世界光源的顏色的話,要去先前提到的#include區域那邊額外加入 #include "UnityLightingCommon.cginc")
這邊讓我們特別提一下dot這個函式。
(dot示意圖)
我自己是習慣稱dot為重疊度運算,它會回傳-1~1之間的數字,當兩者向量朝同個方向平行時會回傳1,若為反方向的話則回傳-1,我們可以用此方法去計算該頂點的法向量受到多大程度的光照影響。

接著讓我們看看混和後的效果。
(完整的運算邏輯)
(混和後的效果)
然而這時候大家應該會發現一個問題……

如果轉到背光面的話就整個暗掉了! 而我們想要的應該是至少留有環境光那均勻而微弱的光照
為什麼會這樣呢? 讓我們再看一次dot的運算吧。
如果我們今天繪製背光處的時候,由於其法線向量與看往光源的向量相反,使的dot回傳負數結果,這會讓我們剛才最後進行光照混和時,diffuse的運算結果反過來消去了ambient的數值,甚至產生負數的向量,而任何顏色只要乘以0或更小的值都會變成黑色的 (黑色的rgb值為000)。

為了避免這種狀況發生,我們會需要特別加個限制
如此一來就能至少看到Ambient的效果了!

specular(高光)
最後就讓我們來看specular的部分吧! 這一部分所代表的是一個具有光澤感的物體上所產生的亮點,它是光線打在物體表面後,直接射入我們眼中的部分。 (怎麼聽起來怪怪的)


在遊戲裡頭,眼睛指的基本上就是Camera,因此這裡我們要先取得攝影機的位置。

同時我們還會需要頂點的確切位置(或著說世界座標),這樣子才能去計算頂點到我們眼中的向量。
使用前要先在Vertex Shader裡面做轉換 (拿頂點去跟unity_ObjectToWorld矩陣做相乘,不過具體上數值算起來長什麼樣子我就不太了解了。)

接著來看看邏輯的部分吧!
先利用攝影機的位置去求出視線的向量(物體頂點往眼睛,記得向量要單位化),再將此向量拿去跟反射的向量做dot運算,求出反射光打到眼中的強度,乘上光源顏色即可。
最終再將三種光照(環境/漫射/高光)疊加在一起,拿去跟原色做混和即可。

來看看效果吧!
這裡我們還可以額外宣告一個控制高光強度的變數——Gloss(光澤度,有點像物體的反射強度),先在Properties那邊新增了以後我們就可以在計算Specular的地方加入。
(光澤度的運算為原高光強度轉成X次方)
接著我們就可以在編輯器那邊調整了,光澤度越高的物體,高光面積就會小,但也越亮。

好啦,那整體來說Phong Lighting已經算完成了,但是到這裡時,可能有人會發現有些奇怪的地方,讓我們先把之前扔給材質球的貼圖拿掉,換成最普通的顏色來看。
你會發覺高光的部分其實並沒有很平整,反而邊角帶有一點鋸齒的感覺,這是為什麼呢?

就我所知,3D模型基本上只有頂點才具有法向量的資料(並且是長度為1的單位向量),但如果今天要獲得頂點間的法向量呢?
我們不太可能去製作一個完全由頂點構成的3D模型,因此當我們要去存取頂點間的法向量時,他就會給你一個兩頂點間法向量的插值,該向量的值介在兩頂點的法向量之間,但是無法保證該向量長度也會是1,這就使的我們剛才做的部分運算會產生誤差,所幸這個問題很好修改,只要在取得法向量時,先進行一次單位化的動作就好。
接著我們就可以看到比較圓滑的高光了!

好啦,這次就先講到這裡吧,希望這次的筆記大家喜歡~

然後忽然想說一下,最後面混色那一段,我自己因為比較喜歡顯眼一些的高光效果,所以有時會把高光直接加到原色彩上,而不是跟原色彩做混和。
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4752276
All rights reserved. 版權所有,保留一切權利

相關創作

留言共 3 篇留言

樂小呈
佬[e15]

分享ㄍ,裡面有些Shader的教學,但窩看不懂
https://catlikecoding.com/unity/tutorials/

04-25 15:00

pudding
多謝稱讚>< 不過我也看了挺久

你貼的教學感覺蠻廣的呢,我只有稍微看一下,他好像是寫Surface Shader,那部份我也還沒看過XD04-26 16:01
⊰⊱求出處學術用⊰⊱
佬 感謝分享 Phong Shading

04-27 08:47

pudding
多謝捧場! 希望我寫的還算清楚好懂><04-27 12:03

感謝分享,覺得寫得非常詳細,跟著全部做一遍受益良多。但是建議你可以用看看Source Tree (免費的Git),他能夠記錄你所有寫的步驟(包括你所刪除的code與你所增加的code),這樣自己整理時會更加清楚製作的步驟之外,也能讓讀者可以更佳確切地跟者寫,尤其是這些宣告是要在frag裡面,還是在v2f裡面等等,一目了然。希望你繼續創作有關unity shading的內容,非常支持。

04-27 17:00

pudding
非常感謝你的捧場! 抱歉我這麼晚才看到><
我的確有在用SourceTree去跟我的Gitlab連結,不過因為我通常commit的比較不頻繁的關係,所以過程中的程式碼可能就不會留下紀錄 (<-其實就是懶
我應該下次才會改成這樣XD,不過很感謝你的建議!05-10 16:48
我要留言提醒:您尚未登入,請先登入再留言

6喜歡★pudding70119 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:Shader初學筆記... 後一篇:Unity開發者工具初學...

追蹤私訊切換新版閱覽

作品資料夾

aaa1357932大家
各位有空可以來我家看看畫作或聽聽我的全創作專輯!看更多我要大聲說1小時前


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】