我所了解的法線貼圖


兩篇文章

一些基本的概念

1.法線貼圖的定義

顧名思義,法線貼圖保存的是法線的信息貼圖。

2.用來干什么

用來進行凹凸映射。

凹凸映射的目的是使用一張紋理來修改模型表面的法線,以便為模型提供更多的細節。這種方法不會真的改變模型的頂點位置,只是讓模型看起來好像是“凹凸不平”的,但可以從模型的輪廓處看出“破綻”。

有兩種主要的方法可以用來進行凹凸映射:一種方法是使用一張高度紋理(height map)來模擬表面位移(displacement),然后得到一個修改后的法線值,這種方法也被稱為高度映射(height mapping);另一種方法則是使用一張法線紋理(normal map)來直接存儲表面法線,這種方法又被稱為法線映射(normal mapping)。盡管我們常常將凹凸映射和法線映射當成是相同的技術,但要知道它們之間的不同。

3.種類

  • 世界空間下的法線紋理
  • 模型空間下的法線紋理
  • 切線空間下的法線紋理

對比不同的法線貼圖

  • 首先按照不同的坐標系得到了不同類型的法線貼圖。模型頂點的法線根據所處坐標系的不同,在成圖后表現也是不同的。以模型法線貼圖和切線法線貼圖為例:

上圖 左邊: 模型空間下的法線紋理 右邊: 切線空間下的法線紋理

  • 不同的顏色是因為法線作為一個Vector3類型的需要轉換到2D的顏色,而通常來說我們可以把顏色的RGB看成一個坐標系,這樣法線就對應了一個RGB顏色。但是法線的范圍是[-1,1],而顏色是沒有賦值的,因此有以下的轉換過程。

法線紋理存儲的是表面的法線方向。由於法線方向的分量范圍在[-1, 1],而像素的分量范圍為[0, 1],因此我們需要做一個映射,通常使用的映射就是:
pixel=(normal + 1) / 2
這就要求,我們在Shader中對法線紋理進行紋理采樣后,還需要對結果進行一次反映射的過程,以得到原先的法線方向。反映射的過程實際就是使用上面映射函數的逆函數:
normal=pixel × 2 - 1

1.world space normal map

一旦從貼圖里解壓出來后,就可以直接用了,效率很高.但是有個缺點,這個world space normal 是固定了,如果物體沒有保持原來的方向和位置,那原來生成的normal map就作廢了。

  • 世界坐標下的頂點的法線是現成的,因此好用。不過如果進入模型在U3D里面進行了位置或者方向的轉換,那么在沒有轉換矩陣的情況下,法線信息就是錯誤的,也就無法使用了。進一步思考如果場景中存在大量的靜態模型,可以考慮用這個。

2.object space normal map

對於模型頂點自帶的法線,它們是定義在模型空間中的,因此一種直接的想法就是將修改后的模型空間中的表面法線存儲在一張紋理中,這種紋理被稱為模型空間的法線紋理(object-space normal map)。

  • 對象空間的法線貼圖,這個貼圖中記錄的法線信息是基於模型空間的,因此數值是相對的,這樣模型在場景中是可以位移和旋轉的,只要在計算的時候乘上對應的矩陣即可。而且從上面的圖里可以看到貼圖是彩色的,因為模型上的頂點法線在這個空間中是朝各個方向的。

  • 對象空間的法線貼圖比起世界空間的在使用了已經有了很大的進步,不過它仍舊有自己的局限性,就是這樣的貼圖還是依賴於模型本身。從其定義也可以看出來,它也是一種“絕對位置”。如果模型發生了形變,則這個貼圖的信息就是錯誤的。從目前來看,我只能想到模型在場景中存在動畫這個問題。

3.tangent space normal map

對於模型的每一個頂點,它都有一個屬於自己的切線空間,這個切線空間的原點就是該頂點本身,而z軸是頂點的法線方向(n),x軸是頂點的切線方向(t),而y軸可由法線和切線叉積而得,也被稱為副切線(bitangent, b)或副法線。這種紋理被稱為是切線空間的法線紋理(tangent-space normal map)。

  • 定義很好理解,從本質上講切線空間的法線貼圖解決了模型變形的問題。因為在另一個模型上的頂點的切線空間坐標系里面,法線貼圖中的信息是可以使用的,它不依賴於模型本身、也不依賴於模型所處的坐標系。

4.切線空間下的法線貼圖如何生成

  • 以3DMAX為例,法線貼圖需要高模和低模配合,具體過程不說了,網上大把的視頻。
  • 重點是法線貼圖的生成需要高模和低模,因為沒有高模就不知道法線方向,沒有低模,就不知道高模上某點的法線對應於低模上哪個點。
  • 下面才是重點,因為多個高模的面使用了同一個低模的面,因此在生成法線貼圖時,高模不能使用自己的tangent space,而是使用低模的tangent space。這樣一些高模上的點的法線與低模面上的法線出現了不一致,你可以想象低模上的某個面上的法線指向一個方向,但是對應了幾個高模的點,可能一些點的法線與低模面的法線方向一樣,那么很好,完美融入低模的切線空間,顏色呈現出淡藍色。但是其它那些和低模面法線不一致的點的法線就產生了夾角,就造成了在切線法線貼圖上那些不是[0.5,0.5,1]色值的點。

低模上的這個tangent space,也必須與高模上的坐標系tangent space。因為低模上的一個面,可能對應了高模上的幾個面(精度高),按照新方法每個面都有一個局部坐標系,那對於低模上的每個面,高模因為存在好幾個面,就會出現好幾個局部坐標系,這肯定是不行的。所以高模所用的tangent space,就是低模上的。生成法線貼圖,必定會確認高模上哪些面都對應低模上的哪個面,然后高模上的這幾個面的法線,都會轉換為低模這個面上所構建的tangent space的坐標。這樣,當低模變形時,即三角面變化時,它的tangent space也會跟着變化,保存在貼圖里的法線乘以低模這個面的tangent space到外部坐標系的轉換矩陣即可得到外部坐標。順便再提一點,高模保存的這個法線,是高模上object space里的法線。

  • 對於上述的內容,這張圖做了很好的詮釋。

如何將高模的法線貼圖用在低模上

  • 對於object space normal map,低模的object space坐標系與高模中的object space坐標系是重合的。所以不需要構建,所以低模上某點才能直接用高模的法線替換自己的法線。


免責聲明!

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



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