一、概述html
上一篇博客,3D遊戲經常使用技巧Normal Mapping (法線貼圖)原理解析——基礎篇,講了法線貼圖的基本概念和使用方法。而法線貼圖和通常的紋理貼圖同樣,都須要進行壓縮,也須要生成mipmap。可是因爲法線貼圖存儲的是法線信息,壓縮和生成mipmap的方法天然會有所變化。app
如今已經許多用於法線貼圖壓縮和生成mipmap的工具,大部分商業遊戲引擎也集成了相關方法,只須要點幾下鼠標就能夠完成。本文僅針對法線貼圖的紋理壓縮和mipmap的方法進行原理性的說明,至於在具體的工具中如何操做,能夠參看相關工具的說明文檔。工具
法線貼圖壓縮的中文資料仍是比較多的,也不太複雜;可是生成mipmap的方法中文資料很少,《Real-Time Rendering 3rd》講解的比較詳細,本文的這部份內容主要來源於這本書,若是想詳細瞭解的,能夠看原書,網上有電子版。spa
二、法線貼圖的壓縮3d
傳統的jpg等壓縮方式解壓時間太長,且壓縮比不固定,因此在實時渲染中通常採用DXTC及其改進方法,簡單來講,就是把4*4的像素當作一個Block,對其進行簡化表示,詳情參見百度百科http://baike.baidu.com/view/736449.htm。因爲法線貼圖存儲的數據並非RGB信息而是法線方向,因此須要在通常紋理壓縮的方法的基礎上進行必定的改變。orm
壓縮的第一步很簡單,因爲歸一化的法線長度爲1,且在切線空間下,法線的z份量不可能爲負數,因此只須要存儲x和y值便可。本文的壓縮方法在這一步壓縮的基礎上,利用現有的紋理壓縮方法,進行進一步壓縮。htm
在支持DirectX10的顯卡上,可使用BC5格式進行壓縮。BC5的壓縮方法內存狀況如圖1所示,該格式有兩個顏色通道(R和G),每一個通道使用兩個1Byte的值來表示,每一個像素使用3Bit在這兩個顏色值之間進行插值。將法線貼圖中每一個法線的x和y值利用BC5格式進行壓縮,如圖2所示。對每一個Block(16個像素)存儲x的最大、小值和y的最大、小值,而後每一個像素利用3Bit進行插值,至關於在圖2右圖所示的8*8區域內取樣(爲了簡化表示,圖2只畫了4*4點)。blog
圖1 BC5壓縮方法遊戲
圖2 法線貼圖壓縮示意圖,右圖框內應該是8*8個點,爲了畫圖方便簡單表示爲4*4ip
對於不支持DirectX10的顯卡,可使用DXT5格式進行壓縮(DXT5爲DirectX9.0的紋理壓縮格式,若是連DirectX9.0都不支持,建議直接送博物館),將法線的x和y值存儲到紋理的alpha和Green通道便可。之因此是存儲到這兩個通道,而非其餘通道,是由於每一個DXT5中每一個Block選擇的兩個參考像素alpha通道有8Bit,RGB通道分別爲五、六、5Bit,因此使用alpha和Green通道能夠得到較高精度。
三、法線貼圖的mipmap
使用通常紋理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。法線貼圖對於鏡面反射的mipmap如圖3所示,第一幅圖中有4個像素,每一個像素有法線和鏡面反射波瓣(紅色的是法線,周圍一圈是鏡面反射波瓣,鏡面反射波瓣用於表示不一樣方向的反射強度)。圖2中間部分,表示正確的mipmap狀況,分別從4個像素合併爲2個像素,從兩個像素合併爲1個像素。而現有的方法中,沒有方法能夠作到這樣的mipmap,因此只能用其餘方法進行近似。
圖3 法線貼圖的mipmap示意圖
圖2的底部左圖,是使用通常紋理的mipmap方法對法線進行平均,能夠看到這種方法產生出的鏡面反射波瓣和正確的鏡面反射波瓣差距很大,其根本緣由是使用線性方法對非線性的參數進行計算。圖2底部圖右圖,每次在平均法線的同時,改變表面的光澤度(即改變鏡面光公式中的m),雖然最終結果與正確的mipmap有一些差距,可是比通常紋理的mipmap的方法要好不少。
因此,對法線貼圖的mipmap方法之一,就是在使用通常紋理的mipmap方法對法線進行平均的同時,每張mipmap都必須附帶一張光澤貼圖(gloss map),記錄每一個像素點的光澤度(即m),m的計算原則就是讓最後的鏡面反射波瓣與正確的鏡面反射波瓣最接近。固然,還有其餘不少方法能獲得不錯的結果,具體能夠參看《Real-Time Rendering 3rd》,或去搜索相關論文。
參考資料
[1]Akenine-Möller T, Haines E, Hoffman N. Real-time rendering 3 [M].