騰訊遊戲學院專家帶你快速瞭解PBR
相信很多人和我一樣,剛開始學PBR的時候被一大堆名詞直接搞懵逼:BRDF、GGX、半球積分、輻射度、立體角……都是些什麼啊?這還沒完,各種公式居然……全是積分!
所以我還是儘量簡單的描述PBR中各個組成部分的意義,迴避枯燥的推導過程直接看結果,讓大家首先了解到整體的框架和思路。有興趣的同學可以在本文之後繼續研究其物理本質,沒時間深究的同學也能照著公式讀寫程式碼。
回顧
首先我們回顧一下Blinn-Phong光照公式:
這是個常用的光照公式,其中:
是漫反射顏色;
是高光顏色,或者叫鏡面反射的顏色;
是表面法線和光線方向的點乘,結果是兩個向量的餘弦,下文也寫做 ;
是表面法線和半形向量的點乘,也是它們的餘弦,下文也寫作 ,半形向量是視線向量和光線向量的中間值,既Normalized(L + V), 順便補充一下,下文還會把法線與視線的餘弦寫作 ;
m用來控制高光的擴散範圍,越大時,光斑越集中,越小時,光斑約分散。
為了少寫幾個變數,同時讓腦子少繞點彎,我們把公式改寫成這樣:
這個公式很簡單,而且GPU計算起來也很高效,不過效果上確是一般般,下面介紹一版改進版本的公式:
這個新公式的變化主要有三點:
1)Diffuse光增加了一個(1/π)的係數 ,它會讓我們在給光源設定Diffuse的時候更加直觀,不過很多時候引擎會將這個步驟在內部預先進行處理。
2)高光也增加了一個係數,這個係數很有意思:在原公式中,m越大高光的光斑越集中,加上這個引數後我們發現,m越大除了讓光斑越集中,還能讓高光更亮。這是很合理的物理現象,光的能量越密集,單位面積上的強度就越大,總能量不變。這個做法叫“歸一化”。
3) 此外高光部分還增加了與 相乘的部分,有點類似Diffuse了。這個其實是更接近真實的情況,因為所有光線照射的效果都需要考慮受光面傾斜的情況,只是老公式認為在高光部分這個影響不明顯,於是省略掉以節省效能開銷。
分析
當我們在渲染中使用這個公式時,效果已經漂亮不少了。現在我可以告訴大傢什麼是傳說中的BRDF了:
我們看括號裡的部分,這就是一個BRDF。
BRDF不是一個公式,是一類公式,學名“雙向反射分佈函式”,說人話就是:給一個入射角度和一個觀察角度,它能給出一個決定最終射向觀察角度的光的強度的係數(這樣的說法並不嚴謹,但在本文中按這樣理解沒太大毛病),凡是幹這個事情的都叫BRDF函式,有的BRDF函式離真實物理法則更接近,有的則假得一逼。常用的Unity引擎中就包含了三套BRDF公式,用作不同效能機型的適配。
在上面的公式中,紅字部分就是計算這樣的一個係數,留意半形向量是入射向量和觀察向量共同計算出來的。我們把BRDF單獨抽出來寫是這樣的:
下面我們只看BRDF,給這個公式的每個成分再賦予一些意義,讓它顯得高大上一點。
第一部是一個Lambert光照公式,用來計算Diffuse,納尼?好像還缺個 ?注意注意,這個已經被抽取到括號外了,也就是BRDF公式之外,所以括號中的BRDF部分中,我們認為Lambert光照就是第一部分。
現在我們再看一下高光部分:
首先我們看 這個部分,它的作用前面已經講過了,是控制高光產生的光斑的集中度。以一個球體為例,越接近光斑中心,半形向量和法線的夾角越小,高光越亮,越到光斑外圍,半形向量和法線的夾角越大,高光越弱。聽上去挺合理,但翻開物理課本回顧一下就會發現:理論上只有半形向量和法線完全重合的時候才有反射光線被視線接收到,憑什麼這裡還能允許它們存在夾角?而且夾角的變化還導致反射光線強度的變化,這個怎麼來的?
這裡又有一個新的名詞出現了:微表面。我們在渲染中是逐個畫素進行處理的,每個畫素雖然足夠小了,但在這個畫素覆蓋的範圍內還有無數細微的起起伏伏的物理結構,有起伏,就會有變化的法線。我們渲染時用到那個畫素法線只能算是所有細微面的法線的平均值,實際上這個畫素點內部朝各個方向的法線都是有的,只是所佔比例有所不同。
在渲染的時候我們當然不會把畫素內部的法線逐個取出來再去計算光照,這麼做也未免太二了,我們只需要把能反射到視線的法線所佔的比例找出來,用它將高光強度修正一下就好了。其實我們常說的“半形向量”就是指能反射到視線的法線。
而我們討論 的部分乾的就是這個事,它根據半形向量和平均法線的夾角,計算出指向半形向量方向的微表面法線的比例。這麼牛逼的事情一定要有個牛逼的名詞來描述它,就叫“法線分佈函式”,縮寫為“NDF”,文中我們以D來表示。
這樣我們的BRDF就可以寫成這樣:
法線分佈函式能解釋表面上細微的凹凸不平對光的反射產生的影響,但是有一個前提:微表面上所有的點都能夠接受到光線,並且能夠反射出光線,事實上真實的物理表面大部分是達不到這樣的條件的,如圖所示:
你看,在這樣的凹凸的表面上,由於自身的遮擋,有很多點根本無法接受到入射光線,也有很多點反射的光線無法射出表面。因此,我們此處再定義一個函式叫“可見性函式”,本文中用V來表示。它的作用就是根據給定的入射光線和出射光線的方向,計算出不被自身遮擋的光線的比例。回頭看看我們的BRDF公式裡,貌似沒有啊?沒關係,請看:
定義V為常量1……怎麼樣?是不是被我的機智打敗了。
最後只剩一個東西要講解一下了,就是高光強度 ,在公式中,這是個常量,但卻不是符合真實物理規律的。在物理書講反射與折射的章節上我們學過,在一個反射面上,當入射角度越“傾斜”,反射的光線越多,折射的光線越少,入射角度越“直”,折射的光線越多,反射的越少。這個現象叫做菲涅爾現象。所以這裡的高光強度需要用一個函式來表示,本文寫做F。在原公式中我們可以機智的認為它把這個函式也用一個常量函式來表示。
到此為止,我們已經成功把Blinn-Phong光照公式拆解成有物理意義的各個成分,從中也可以看到為什麼我們說這個光照很“假”了:
1)法線分佈函式的自變數基於一個沒有太大物理意義的m。
2)菲涅爾函式是高光常量,表示完全沒有考慮入射光線角度不同帶來的反射變化。
3)可見性函式是常量1,表示所有微表面上的光線完全沒有自遮擋。
4)漫反射和高光之間完全獨立,沒有考慮能量守恆的關係。
為了讓光照達到真實的物理效果,我們就需要逐個解決上面的問題。
基於物理原理進行擴充套件
法線分佈函式
首先看法線分佈函式D,我們需要找一個更符合物理規律並且更容易控制的函式來代替原有的法線分佈函式。在各種常見的PBR模型中被廣泛使用的是Trowbridge-Reitz GGX函式:
其中,Roughness就是我們常說的“粗糙度”,取值範圍為0到1,當取值為1時表示最粗糙的表面,完全沒有任何高光反射。這一點可以從公式中看出來。有的系統例如Unitiy裡用“光滑度”來代替粗糙度,它們的關係是:粗糙度 = 1 - 光滑度。
菲涅爾係數
接下來看菲涅爾函式,我們知道當光垂直射向表面時,折射光線最多,反射光線最少,假設此時的菲涅爾係數是 ,那麼在給定任意角度的時候,可以用下面一個公式來近似的表示這個係數:
這個神祕的 是什麼呢?它是在限定條件下折射和反射的比例,由物質的分子結構決定。是物質的天然屬性。每一種物質都不相同。用一個更常見的說法,它叫做“反射率”。通常通一種物質對不同頻譜的光反射率是不一樣的,所以不管是F還是 都是一組RGB三通道的值。
它的值到底是多少呢?先看一組通過真實物理實驗得到的資料:
我們可以看到,非金屬的反射率都非常小,而金屬的反射率則比較高,大部分在0.5以上,RGB三個通道的差異體現了這種金屬的顏色,值越大則金屬越“亮”。
因此,對於非金屬,我們其實可以用統一的一個比較小的值作為 ,因為效果上差異不會太大,例如Unity引擎裡將這個值定為常數(0.04, 0.04, 0.04),對於金屬,我們以金屬自身顏色Albedo作為它的值。理論上一種物質要麼是金屬,要麼是非金屬,不會出現介於金屬和非金屬之間的狀態。但實際我們做3D渲染的時候,一個畫素面積內是可能同時包含金屬和非金屬的。為了準確描述這種現象,我們定義一個值叫做“金屬度”,當它為1時,反射率完全按金屬的方式處理,為0時,完全按非金屬的方式處理。當取值在0和1之間時,通過線性插值確定反射率:
關於這個通過金屬度計算出來的反射率,在下文中還有更多的意義,不過我們先接著看BRDF公式中剩下的最後一部分:可見性函式。
可見性函式
可見性函式是描述光線從入射到出射的過程中,有多少比例被微表面自身的凹凸不平遮擋住了。這個部分其實和法線分佈有點像,依據的是表面的粗糙程度。為了準確描述,我們首先需要這樣的一個函式:給一個方向,獲得微表面在這個方向上被自遮擋的面積的比例。好的,大神們已經為我們準備好了這樣的一個函式。
Schlick-GGX函式:
公式中的k其實是對粗糙度的一個簡單變形,在只考慮一個固定方向的情況下,這個變形的公式為:
我們最終計算的可見性分了三部分:入射光線沒被遮擋的部分、出射光線沒被遮擋的部分、入射光線被遮擋後,在微表面內部多次反射又射出的部分。我們省略掉推導過程後,得到的公式是這樣:
現在我們回顧一下BRDF公式:
至此,公式中V、D、F三個部分我們都已經給出了結論,離最終的結果只剩下一步之遙了。
能量守恆
我們通常會把光照效果分為漫反射和鏡面反射(既高光)兩部分。 傳統意義上說的“漫反射”是指凹凸不平的表面反射的沒有方向性的光。但是我們已經在高光部分充分考慮了物體微表面的變化了啊。而且事實上我們把粗糙度調整為1時,效果跟我們預期的“漫反射”就是一樣的。
而現在BRDF公式中的Diffuse實質上是這樣的:光線射到表面上後,部分被反射,部分被折射而進入材質內部,在材質內部經過多次不規則的折射、反射後,部分光線被吸收,部分光線又從離射入點不遠的地方射出來,這裡的“不遠”是指對映到螢幕後小於一個畫素的大小。因此,材質反射率越高,則越多的光線被直接反射,越少的光線進入材質內部,Diffuse就越低。反之亦然。所以我們還需要兩個係數來修正Specular和Diffuse兩部分:
我們根據能量守恆的原則可知,Diffuse、高光能量之和一定小於或等於入射光的總能量,少的那部分是被吸收的部分,從前文的分析我們還可以肯定被吸收的部分一定是在被折射的光線中扣除的。從物理性質上來說,金屬幾乎吸收全量的折射光線,非金屬則不怎麼吸收光線。
根據這樣過的幾個性質,我們得到這樣的近似的關係:首先高光係數其實就是前文所描的反射率 ,因為它正好描述有多少光的能量會被高光反射出來。
然後,Diffuse係數則是剩餘部分扣除吸收的光線,而由於金屬吸收光線,所以通過金屬度來近似的計算吸收的光線比例:
有了這個之後,PBR中能量守恆原則的得到描述,我們對前文提出的幾個問題算是完成了回答。
總結
現在給出一個圖來梳理一下本文中各個公式的關係:
需要注意的是這裡的各個部分的公式並不是唯一的公式。在各大遊戲引擎中都有根據效能、效果、應用環境的不同而使用的不同演算法。但思想是一致的。除此之外,還是建議大家繼續研究正經一點的PBR理論基礎,理解輻射度、光照能量等相關物理概念。以便在更復雜的光照環境中游刃有餘的解決問題。
關於騰訊遊戲學院專家團
如果你的遊戲也富有想法充滿創意,如果你的團隊現在也遇到了一些開發瓶頸,那麼歡迎你來聯絡我們。騰訊遊戲學院聚集了騰訊及行業內策劃、美術、程式等領域的遊戲專家,我們將為全世界的創意遊戲團隊提供專業的技術指導和遊戲調優建議,解決團隊在開發過程中遇到的一系列問題。
專案指導合作請聯絡微信:18698874612
作者:董根
來源:騰訊GWB遊戲無界
原地址:https://mp.weixin.qq.com/s/mgHA2uTFawAYjIcnSuW3Gw
相關文章
- 騰訊遊戲學院專家:PBR渲染模型的理論及具體應用遊戲模型
- 如何應對CPU幀率瓶頸和卡頓?騰訊遊戲學院專家帶你剖析遊戲
- 騰訊遊戲學院專家:如何避免出海遊戲伺服器水土不服?遊戲伺服器
- Crash率10%降至1%,騰訊遊戲學院專家是這樣打磨遊戲的遊戲
- 騰訊遊戲學院專家:UE高階效能剖析技術之RHI遊戲
- 騰訊遊戲學院專家:做一個多執行緒遊戲框架可以多簡單?遊戲執行緒框架
- 省頻寬、耗電小,騰訊遊戲學院專家解析手遊渲染架構遊戲架構
- 帶你快速瞭解HTMLHTML
- 斷線卡頓怎麼辦?騰訊遊戲學院專家談網路遊戲同步技術遊戲
- 騰訊遊戲學院專家例項剖析:如何優化休閒遊戲的美術風格?遊戲優化
- 騰訊遊戲學院專家:手遊開發,該如何做好Android記憶體優化?遊戲Android記憶體優化
- 騰訊遊戲學院專家眼中,是如何看待遊戲設計時常遇見的三個問題遊戲設計
- 騰訊遊戲學院專家:如何延長玩家遊戲時間,並調動玩家二次創作?遊戲
- 騰訊遊戲學院專家教你七步做數值遊戲
- 你真的瞭解python嗎?這篇文章帶你快速瞭解!Python
- 帶你快速瞭解 MongoDB 分散式叢集MongoDB分散式
- 騰訊遊戲學院圓桌:《妄想山海》的打磨之路遊戲
- 打造獨立遊戲孵化新模式,騰訊遊戲學院助力遊戲多元發展遊戲模式
- 帶你瞭解webpackWeb
- 熱愛遊戲的你是否真的瞭解遊戲?遊戲
- 遊戲開發中最容易忽略的一環:遊戲音訊你瞭解多少?遊戲開發音訊
- 帶你瞭解騰訊開源的多渠道打包技術 VasDolly原始碼解析原始碼
- 遊戲技能該如何設計?這二篇乾貨帶你瞭解遊戲
- 一文帶你全面瞭解網路遊戲的社交生態遊戲
- 騰訊光子專家:遊戲互動設計師如何在遊戲體驗上創新?遊戲
- web伺服器軟體有哪些?帶你快速瞭解Web伺服器
- 騰訊在海外投了這37家遊戲公司遊戲
- python程式設計師告訴你,python怎麼學?13個特性帶你快速瞭解pythonPython程式設計師
- 創夢天地攜手騰訊引進海外創意遊戲 推出新遊《帶你回家》遊戲
- 帶你瞭解遊戲陪玩系統原始碼前端常用的儲存方式遊戲原始碼前端
- 萬字帶你瞭解ChatGLM
- 什麼是雲連線?雲學院帶你瞭解華為雲連線知識
- 優思學院|一篇文章帶你瞭解什麼是六西格瑪
- 共享WiFi專案盈利如何?一文帶你瞭解WiFi
- 大屏視覺化知多少?3分鐘帶你快速瞭解視覺化
- 帶你瞭解代理 IP 那些事
- 帶你了從零瞭解DockerDocker
- 帶你瞭解 Angular 與 Angular JSAngularJS