渲染篇:法線貼圖


今天接着講渲染基礎:就是下面的法線貼圖了。

 

什么是法線貼圖?

法線貼圖這個東西,只要搞渲染算法的肯定會遇到。簡單來講,法線就是指模型表面的凹凸感,而凹凸感的產生是因為模型表面像素的光照條件不一樣產生的。比如下面這個圖,邊緣光照壓暗了,所以給人有一種凹凸3D感覺。

但凹凸感跟法線貼圖有什么關系?

在逐像素計算光照時,每一個像素都會根據該點的法向量來計算最終該點的光照結果,那么,我們如果能夠改變這個法線的方向,就可以改變這個點的光照結果,進而影響模型表面凹凸感。比如,高模在計算光照時,每個面的法線方向不同,所以各個面的光照計算結果都不同,就有凹凸的感覺了,而有的低模只有一個面,整個面的光照條件都是一致的,就沒有凹凸的感覺了。如果我們把高模的法線信息保存下來,類似紋理貼圖那樣,存在一張圖里,再給低模使用,低模就可以有跟高模一樣的法線,進而在計算光照時達到和高模類似的效果,這也就是常說的烘法線的原理。

 

知道了概念,再來看看實現。

最早的法線貼圖實現方式是使用凹凸貼圖(Bump Map),簡單來講就是給一張灰度圖,默認為黑色,越凸起的地方顏色越亮,通過采樣點之間斜率決定像素是否位於邊緣,從而影響光照明暗,不過這種方式已經過時了,具體細節不再贅述。

Unity法線貼圖一般都是存儲在切線空間。這跟世界空間、模型空間類似,只不過這個空間稍有點不直觀。大家只要知道這是為了解耦就行,比如最直觀是將不同頂點的法線值存儲在世界空間,理解和計算都方便,但是這樣會有弊端,就是當模型發生旋轉等變化時,同一頂點的法線值就會發生變化,也就是需要多份法線貼圖,這顯然是極其浪費的。如何保證同一模型共用一份法線貼圖呢?答案就是將法線值存儲在切線空間。切線空間的z軸就是頂點所在面的法線方向,該點的uv二維坐標系則用來表達該點的切線(tangent)和該點的次法線(binormal)方向,具體計算如下:

T = normalize(dx/du, dy/du, dz/du)

N = T × normalize(dx/dv, dy/dv, dz/dv)

B = N × T

OK,知道法線貼圖存儲的是切線空間法線值,那么就可以開始了。首先在頂點着色器中,存儲模型的切線空間到世界空間的轉換矩陣。

片元着色器采樣法線貼圖,映射計算,空間轉換。

這中間有一步映射計算,大致就是因為法線貼圖存儲的值是有限范圍(比如8bits是0~255),歸一化就是0到1;而法線值是-1到1,所以需要乘以2減去1,只不過這里Unity給我們封裝好了。

 

看下效果:

我們增大下法線強度。從法線貼圖中獲取到的是這個采樣點對應的法線方向,光滑的部分法線方向都為垂直於表面豎直向上的方向,也就是(0,0,1)的方向,而有凹凸的地方,法線就會有偏移值,換句話說,我們讓法線貼圖采樣出來的方向越偏離(0,0,1)方向,就會越加強法線的效果。

結果:

我們應用到前面文章講過的BlinnPhong模型,增加法線貼圖效果,看下對比:

從左到右分別是:直接貼圖采樣、BlinnPhong模型、增加法線貼圖的BlinnPhong模型。

 

本節內容就介紹到這里,有問題歡迎留言或私聊~~~

歡迎關注我的微信公眾號【unity大話東游】,更多的unity技術類和渲染類文章等着你哦!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM