3D游戲常用技巧Normal Mapping (法線貼圖)原理解析——高級(jí)篇

1、概述

上一篇博客,3D游戲常用技巧Normal Mapping (法線貼圖)原理解析——基礎(chǔ)篇,講了法線貼圖的基本概念和使用方法。而法線貼圖和一般的紋理貼圖一樣,都需要進(jìn)行壓縮,也需要生成mipmap。但是由于法線貼圖存儲(chǔ)的是法線信息,壓縮和生成mipmap的方法自然會(huì)有所變化。

現(xiàn)在已經(jīng)許多用于法線貼圖壓縮和生成mipmap的工具,大部分商業(yè)游戲引擎也集成了相關(guān)方法,只需要點(diǎn)幾下鼠標(biāo)就可以完成。本文僅針對(duì)法線貼圖的紋理壓縮和mipmap的方法進(jìn)行原理性的說明,至于在具體的工具中如何操作,可以參看相關(guān)工具的說明文檔。

法線貼圖壓縮的中文資料還是比較多的,也不太復(fù)雜;但是生成mipmap的方法中文資料不多,《Real-Time Rendering 3rd》講解的比較詳細(xì),本文的這部分內(nèi)容主要來源于這本書,如果想詳細(xì)了解的,可以看原書,網(wǎng)上有電子版。

2、法線貼圖的壓縮

傳統(tǒng)的jpg等壓縮方式解壓時(shí)間太長,且壓縮比不固定,所以在實(shí)時(shí)渲染中一般采用DXTC及其改進(jìn)方法,簡單來說,就是把4*4的像素當(dāng)做一個(gè)Block,對(duì)其進(jìn)行簡化表示,詳情參見百度百科http://baike.baidu.com/view/736449.htm。由于法線貼圖存儲(chǔ)的數(shù)據(jù)并不是RGB信息而是法線方向,所以需要在一般紋理壓縮的方法的基礎(chǔ)上進(jìn)行一定的改變。

壓縮的第一步很簡單,由于歸一化的法線長度為1,且在切線空間下,法線的z分量不可能為負(fù)數(shù),所以只需要存儲(chǔ)x和y值即可。本文的壓縮方法在這一步壓縮的基礎(chǔ)上,利用現(xiàn)有的紋理壓縮方法,進(jìn)行進(jìn)一步壓縮。

在支持DirectX10的顯卡上,可以使用BC5格式進(jìn)行壓縮。BC5的壓縮方法內(nèi)存情況如圖1所示,該格式有兩個(gè)顏色通道(R和G),每個(gè)通道使用兩個(gè)1Byte的值來表示,每個(gè)像素使用3Bit在這兩個(gè)顏色值之間進(jìn)行插值。將法線貼圖中每個(gè)法線的x和y值利用BC5格式進(jìn)行壓縮,如圖2所示。對(duì)每個(gè)Block(16個(gè)像素)存儲(chǔ)x的最大、小值和y的最大、小值,然后每個(gè)像素利用3Bit進(jìn)行插值,相當(dāng)于在圖2右圖所示的88區(qū)域內(nèi)取樣(為了簡化表示,圖2只畫了44點(diǎn))。

image

圖1 BC5壓縮方法

image

圖2 法線貼圖壓縮示意圖,右圖框內(nèi)應(yīng)該是88個(gè)點(diǎn),為了畫圖方便簡單表示為44

對(duì)于不支持DirectX10的顯卡,可以使用DXT5格式進(jìn)行壓縮(DXT5為DirectX9.0的紋理壓縮格式,如果連DirectX9.0都不支持,建議直接送博物館),將法線的x和y值存儲(chǔ)到紋理的alpha和Green通道即可。之所以是存儲(chǔ)到這兩個(gè)通道,而非其他通道,是因?yàn)槊總€(gè)DXT5中每個(gè)Block選擇的兩個(gè)參考像素alpha通道有8Bit,RGB通道分別為5、6、5Bit,所以使用alpha和Green通道可以獲得較高精度。

3、法線貼圖的mipmap

使用一般紋理mipmap方法生成的法線貼圖對(duì)于漫反射表面基本沒問題,但是在鏡面表面會(huì)導(dǎo)致嚴(yán)重的視覺問題。對(duì)于漫反射表面來說,光照的計(jì)算公式為l·n,l為光線方向的相反方向,n為法線,l·n1 + l·n2 + l·n3 + l·n4 = l·(n1 + n2 + n3 + n4) / 4,而mipmap則是事先計(jì)算(n1 + n2 + n3 + n4) / 4,所以對(duì)于漫反射表面,對(duì)法線貼圖使用傳統(tǒng)方式的mipmap基本沒問題。為什么是基本沒問題而不是完全沒問題呢?因?yàn)檫@里存在一個(gè)近似,若l·**n **< 0,則光照值為0(光照不能為負(fù)),若將這個(gè)因素考慮進(jìn)去,漫反射表面也會(huì)有問題,不過在實(shí)際當(dāng)中這種情況表現(xiàn)不明顯,所以可以認(rèn)為基本沒問題。

對(duì)于鏡面表面來說,當(dāng)視線偏離反射光線方向的時(shí)候,光照強(qiáng)度會(huì)急劇下降,反映在公式中是因?yàn)槠浜衏osm(h·n)項(xiàng)(具體公式可以Google),而漫反射光照是線性變化,所以對(duì)于鏡面表面,不能使用傳統(tǒng)方法生成法線貼圖的mipmap。法線貼圖對(duì)于鏡面反射的mipmap如圖3所示,第一幅圖中有4個(gè)像素,每個(gè)像素有法線和鏡面反射波瓣(紅色的是法線,周圍一圈是鏡面反射波瓣,鏡面反射波瓣用于表示不同方向的反射強(qiáng)度)。圖2中間部分,表示正確的mipmap情況,分別從4個(gè)像素合并為2個(gè)像素,從兩個(gè)像素合并為1個(gè)像素。而現(xiàn)有的方法中,沒有方法可以做到這樣的mipmap,所以只能用其他方法進(jìn)行近似。

image

圖3 法線貼圖的mipmap示意圖

圖2的底部左圖,是使用一般紋理的mipmap方法對(duì)法線進(jìn)行平均,可以看到這種方法產(chǎn)生出的鏡面反射波瓣和正確的鏡面反射波瓣差距很大,其根本原因是使用線性方法對(duì)非線性的參數(shù)進(jìn)行計(jì)算。圖2底部圖右圖,每次在平均法線的同時(shí),改變表面的光澤度(即改變鏡面光公式中的m),雖然最終結(jié)果與正確的mipmap有一些差距,但是比一般紋理的mipmap的方法要好很多。

所以,對(duì)法線貼圖的mipmap方法之一,就是在使用一般紋理的mipmap方法對(duì)法線進(jìn)行平均的同時(shí),每張mipmap都必須附帶一張光澤貼圖(gloss map),記錄每個(gè)像素點(diǎn)的光澤度(即m),m的計(jì)算原則就是讓最后的鏡面反射波瓣與正確的鏡面反射波瓣最接近。當(dāng)然,還有其他很多方法能得到不錯(cuò)的結(jié)果,具體可以參看《Real-Time Rendering 3rd》,或去搜索相關(guān)論文。

參考資料

[1]Akenine-M?ller T, Haines E, Hoffman N. Real-time rendering 3 [M].

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容