3D遊戲常用技巧Normal Mapping (法線貼圖)原理解析——基礎篇
1、法線貼圖基本概念
在製作3D遊戲時,常常遇到這樣一個問題:一個平面,這個平面在現實中並不是一 個“平”面,例如磚牆的表面帶有石質浮雕等等。這種情況下如果只是簡單的做一個平面,則讓人感覺嚴重失真,如圖1所示;而如果用很密集的三角形去表示這類略有凹凸的表面,則效能上大大下降。研究人員發現,人眼對物體的凹凸感覺,很大程度上取決於表面的光照明暗變化,如果能通過一張貼圖在一個平面上表現出由凹凸造成的明暗變化,則可以讓人眼感覺這個平面是凹凸不平的(雖然這個平面還是平的)。法線貼圖正是為了這個目的而產生的。
圖1 不同細節程度的蠟燭
準確的說,法線貼圖是Bump Mapping(凹凸貼圖)的其中一種。第一個Bump Mapping由Blinn在1978年提出,目的是以低代價給予計算機幾何體以更豐富的表面資訊。30年來,這項技術不斷延展,尤其是計算機圖形學成熟以後,相繼出現了不少演算法變體,法線貼圖就是其中很重要的一種。研究人員對法線貼圖進一步改進,出現了Parallax Mapping(視差貼圖), Relief Mapping等技術,實現了更逼真的效果。本文僅針對法線貼圖進行介紹。
一條法線是一個三維向量,一個三維向量由x, y, z等3個分量組成,在法線貼圖中,把(x, y, z)當作RGB3個顏色的值儲存(如圖2),並將其每個分量對映到[-1, 1]。例如,對於x, y, z各有8位的紋理,[0, 128, 255]表示法向量(-1, 0, 1)。
圖2 利用彩色通道儲存法線貼圖
2、切線空間
法線貼圖中儲存的法線最初是定義在世界空間中,但在實際中,這種方式很少見,因為只要物體移動,法線貼圖則不再有效。另一種方式就是將法線儲存在物體的區域性空間中,物體可以進行剛體變換(平移,旋轉,縮放),法線貼圖依舊有效,但是這種方法並不能應對任何方式的變換,並且法線貼圖不能在不同物體進行復用,增加了美工的負擔。所以,現在現在普遍採用的解決方案是將法線儲存在切線空間中。
簡單的來說,切線空間可以理解為紋理空間的u,v方向和法向量n,這3個方向構成了切線空間,一般使用T、B和N表示,如圖3所示。具體解釋見http://blog.csdn.net/bonchoix/article/details/8619624,這個部落格解釋的很好,沒見過的童鞋可以看一看,第一次理解可能會有點困難。
圖3 切線空間
3、法線貼圖的使用
法線貼圖的製作過程如圖4所示,通過對比高模和低模的差異,生成法線貼圖,在執行時使用法線貼圖+低模即可表現出接近高模的效果,但是大大降低了顯示卡的負擔。計演算法線貼圖的演算法在3ds Max中已實現,美術人員只需針對同一個模型製作一個高模和一個低模,烘焙出一張法線貼圖,在遊戲中使用低模+法線貼圖即可。
圖4 法線貼圖製作過程
在渲染模型表面的時候,需保證光照方向和法線是處在同一座標空間。光照方向在世界空間中,而法線在切線空間,將他們變換到同一座標空間無非兩種方法:
1、將光照方向變換到切線空間;
2、將法線變換到世界空間。
在大部分情況下,使用第一種方案會比較好,因為只需針對每個頂點進行變換,然後在三角形中對變換後的光照方向進行插值;而使用第二種方案,則需要對每個畫素進行變換。顯然,在光源較少的情況下,使用第一種方案可以減少計算量。當然,在光源數量較多的情況下,到底使用那種方案,需要值得考慮,因為使用第二種方案只需要變換一次法線,而第一種方案需要有多個光照方向需要變換。
值得注意的是,第一種方案中的插值對於點光源來說存在一個近似,光照方向在一個三角形上變化的很慢,所以可以進行插值,不過對於方向光則沒有這個問題。
4、法線貼圖效果
法線貼圖+低模可以表現出接近高模的效果,在圖4中可以看到,加上法線貼圖的低模,效果很接近高模;圖5為unity3d中法線貼圖的示例,左圖(沒有法線貼圖)和右圖(有加入法線貼圖)相比,明顯右圖的立體感更強。
圖5 unity3d中法線貼圖的示例。左圖中的方塊沒有法線貼圖,右圖加入了法線貼圖
5、法線貼圖的壓縮和mipmap
歸一化的法線長度為1,且在切線空間下,法線的z分量不可能為負數,所以只需要儲存x和y值即可。當然,僅僅是這種簡單的壓縮是不夠的,但是傳統的紋理壓縮方法如DXTC等,不能直接對法線貼圖使用,需要進行一定的變化,具體方法將在下一篇部落格《3D遊戲常用技巧Normal Mapping (法線貼圖)原理解析——高階篇》進行詳細描述。
使用傳統mipmap方法生成的法線貼圖對於漫反射表面基本沒問題,但是在鏡面表面會導致嚴重的視覺問題。對於漫反射表面來說,光照的計算公式為l·n,l為光線方向的相反方向,n為法線,l·n1 + l·n2 + l·n3 + l·n4 = l·(n1 + n2 + n3 + n4) / 4,而mipmap則是事先計算(n1 + n2 + n3 + n4) / 4,所以對於漫反射表面,對法線貼圖使用傳統方式的mipmap基本沒問題。為什麼是基本沒問題而不是完全沒問題呢?因為這裡存在一個近似,若l·n < 0,則光照值為0(光照不能為負),若將這個因素考慮進去,漫反射表面也會有問題,不過在實際當中這種情況表現不明顯,所以可以認為基本沒問題。
對於鏡面表面來說,當視線偏離反射光線方向的時候,光照強度會急劇下降,反映在公式中是因為其含有cosm(h·n)項(具體公式可以Google),而漫反射光照是線性變化,所以對於鏡面表面,不能使用傳統方法生成法線貼圖的mipmap,需要用特殊的技術手段進行處理,具體方法見下一篇部落格“3D遊戲常用技巧Normal Mapping (法線貼圖)原理解析——高階篇”。
參考資料
[1]http://blog.sina.com.cn/s/blog_5497d613010006qu.html
[2]http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.html
[3]http://blog.csdn.net/bonchoix/article/details/8619624
[4]Akenine-Möller T, Haines E, Hoffman N. Real-time rendering 3 [M].
相關文章
- 掌握次世代3D遊戲場景貼圖繪製技巧,半年拿下網易offer3D遊戲
- 法線貼圖那些事兒
- 3D遊戲程式設計與設計4——遊戲物件與圖形基礎3D遊戲程式設計物件
- 遊戲開發3D基礎知識遊戲開發3D
- 零基礎瞭解3D遊戲開發3D遊戲開發
- 【matplotlib基礎】--3D圖形3D
- AI生成遊戲中基於物理的渲染(PBR)貼圖探索AI遊戲
- Kafka原理分析之基礎篇Kafka
- 容器flappybird遊戲——圖文操作指引貼APP遊戲
- Marvelous Designer基礎操作3 - 貼圖匯出
- Groovy基礎語法-字串篇字串
- 《權力的遊戲》3d地圖-基於Mapbox customlayer遊戲3D地圖TOML
- dubbo原始碼解析之基礎篇原始碼
- Dart語法篇之基礎語法(一)Dart
- 前端菜鳥遊戲篇,拼圖遊戲!前端遊戲
- 基礎篇:深入解析JAVA反射機制Java反射
- 3D數學基礎:圖形和遊戲開發(第二版)--讀書筆記(1)3D遊戲開發筆記
- 知識圖譜 KnowledgeGraph基礎解析
- 遊戲基礎知識——“空氣”相關元素的設計技巧遊戲
- 【Android繪圖】繪圖之基礎篇(一)Android繪圖
- Kotlin的語法糖(一)基礎篇Kotlin
- 4、JavaScript進階篇①——基礎語法JavaScript
- 「Golang成長之路」基礎語法篇Golang
- 【.NET基礎】Linq常用語法程式碼演示
- Rhino基礎操作3 - 出圖篇
- 淺談Kotlin語法篇之基礎語法(一)Kotlin
- 基礎篇:深入解析JAVA註解機制Java
- Origin圖表技巧之繪製帶輔助面的3D折線圖3D
- 零基礎學Java-基礎語法篇day1Java
- 0基礎學習建模,3D次世代MAYA遊戲角色建模的方法3D遊戲
- 遊戲互動的基礎!詳細解讀遊戲中最常用的11個控制元件遊戲控制元件
- 遊戲基礎知識——從“增輝龍”和“巴德”看玩家遊戲技巧的三個階段遊戲
- [原始碼解析] TensorFlow 分散式 DistributedStrategy 之基礎篇原始碼分散式
- Presto記憶體調優及原理(基礎篇)REST記憶體
- Go編譯原理系列2(詞法分析&語法分析基礎)Go編譯原理詞法分析語法分析
- WebGL學習之法線貼圖Web
- Vue中的基礎過渡動畫原理解析Vue動畫
- Sealos 基礎教程:Sealos Devbox 的架構原理解析dev架構
- Java基礎知識篇02——Java基本語法Java