天天看點

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

本文由@淺墨_毛星雲 出品,轉載請注明出處。  

文章連結: http://blog.csdn.net/poem_qianmo/article/details/73718109

在計算機圖形學中,紋理貼圖是使用圖像、函數或其他資料源來改變物體表面外觀的技術。這篇文章,将總結和提煉《Real-Time Rendering 3rd》(實時渲染圖形學第三版)的第六章“Texturing(紋理貼圖)”的内容,講述紋理貼圖與其相關技術的方方面面。

簡而言之,通過閱讀這篇總結式文章,你将對紋理貼圖中的以下要點有所了解:

  • 紋理管線 The Texturing Pipeline
  • 投影函數 The Projector Function
  • 映射函數 The Corresponder Function
  • 體紋理 Volume Texture
  • 立方體貼圖 Cube Map
  • 紋理緩存 Texture Caching
  • 紋理壓縮 Texture Compression
  • 程式貼圖紋理 Procedural Texturing
  • Blinn凹凸貼圖 Blinn Bump Mapping
  • 移位貼圖 Displacement Mapping
  • 法線貼圖 Normal Mapping
  • 視差貼圖 Parallax Mapping
  • 浮雕貼圖 Relief Mapping

壹 · 導讀

《Real-Time Rendering 3rd》第六章内容“Chapter 6 Texturing”,讨論了紋理貼圖的方方面面。

在計算機圖形學中,紋理貼圖是使用圖像、函數或其他資料源來改變物體表面外觀的技術。例如,可以将一幅磚牆的彩色圖像應用到一個多邊形上,而不用對磚牆的幾何形狀進行精确表示。當觀察這個多邊形的時候,這張彩色圖像就出現在多邊形所在位置上。隻要觀察者不接近這面牆,就不會注意到其中幾何細節的不足(比如其實磚塊和砂漿的圖像是顯示在光滑的表面上的事實)。通過這種方式将圖像和物體表面結合起來,可以在模組化、存儲空間和速度方面節省很多資源。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖1 一幅使用了紋理顔色貼圖、凹凸貼圖和視差貼圖等方法來增加畫面複雜性和真實感的遊戲截圖(來自《黑暗之魂3》)

貳 · 紋理管線 The Texturing Pipeline

簡單來說,紋理(Texturing)是一種針對物體表面屬性進行“模組化”的高效技術。圖像紋理中的像素通常被稱為紋素(Texels),差別于螢幕上的像素。根據Kershaw的術語,通過将投影方程(projector function)運用于空間中的點 ,進而得到一組稱為參數空間值(parameter-spacevalues)的關于紋理的數值。這個過程就稱為貼圖(Mapping,也稱映射 ),也就是紋理貼圖(Texture Mapping,也稱紋理映射 )這個詞的由來。紋理貼圖可以用一個通用的紋理管線來進行描述。紋理貼圖過程的初始點是空間中的一個位置。這個位置可以基于世界空間,但是更常見的是基于模型空間。因為若此位置是基于模型空間的,當模型移動時,其紋理才會随之移動。

 如圖2 為一個紋理管線(The Texturing Pipeline),也就是單個紋理應用紋理貼圖的詳細過程,而此管線有點複雜的原因是每一步均為使用者提供了有效的控制。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖2 單個紋理的通用紋理管線

下面是對上圖中描述的紋理管線的分步概述:

  • 第一步。通過将投影方程(projector function)運用于空間中的點 ,進而得到一組稱為參數空間值(parameter-space values)的關于紋理的數值。
  • 第二步。在使用這些新值通路紋理之前,可以使用一個或者多個映射函數(corresponder function)将參數空間值(parameter-space values )轉換到紋理空間。
  • 第三步。使用這些紋理空間值(texture-space locations)從紋理中擷取相應的值(obtain value)。例如,可以使用圖像紋理的數組索引來檢索像素值。
  • 第四步。再使用值變換函數(value transform function)對檢索結果進行值變換,最後使用得到的新值來改變表面屬性,如材質或者着色法線等等。
而如下這個例子應該對了解紋理管線有所幫助。下例将描述出使用紋理管線,一個多邊形在給定一張磚塊紋理時在其表面上生成樣本時(如圖3)發生了哪些過程。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖3 一個磚牆的紋理管線過程

如圖3所示,在具體的參考幀畫面中找到物體空間中的位置(x,y,z),如圖中點(-2.3,7.1,88.2),然後對該位置運用投影函數。這個投影函數通常将向量(x,y,z)轉換為一個二進制向量(u,v)。在此示例中使用的投影函數是一個正交投影,類似一個投影儀,将具有光澤的磚牆圖像投影到多邊形表面上。再考慮磚牆這邊,其實這個投影過程就是将磚牆平面上的點變換為值域為0到1之間的一對(u,v)值,如圖,(0.32,0.29)就是這個我們通過投影函數得到的uv值。而我們圖像的分辨率是256 x 256,是以,将256分别乘以(0.32,0.29),去掉小數點,得到紋理坐标(81, 74)。通過這個紋理坐标,可以在紋理貼圖上查找到坐标對應的顔色值,是以,我們接着找到磚塊圖像上像素位置為(81,74)處的點,得到顔色(0.9,0.8,0.7)。而由于原始磚牆的顔色太暗,是以可以使用一個值變換函數,給每個向量乘以1.1,就可以得到我們紋理管線過程的結果——顔色值(0.99,0.88,0.77)。

随後,我們就可以将此值用于着色方程,作為物體的漫反射顔色值,替換掉之前的漫反射顔色。

下面對紋理管線中主要的兩個組成,投影函數(The Projector Function)和映射函數(The Corresponder Function)進行概述。

2.1 投影函數 The Projector Function

作為紋理管線的第一步,投影函數的功能就是将空間中的三維點轉化為紋理坐标,也就是擷取表面的位置并将其投影到參數空間中。

在正常情況下,投影函數通常在美術模組化階段使用,并将投影結果存儲于頂點資料中。也就是說,在軟體開發過程中,我們一般不會去用投影函數去計算得到投影結果,而是直接使用在美術模組化過程中,已經存儲在模型頂點資料中的投影結果。但有一些特殊情況,例如:

1、OpenGL的glTexGen函數提供了一些不同的投影函數,包括球形函數和平面函數。利用空閑時間可以讓圖形加速器來執行投影過程,而這樣做的優點是不需要将紋理坐标送往圖形加速器,進而可以節省帶寬。

2、更一般的情況, 可以在頂點或者像素着色器中使用投影函數,這可以實作各種效果,包括一些動畫和一些渲染方法(比如如環境貼圖,environment mapping,有自身特定的投影函數,可以針對每個頂點或者每個像素進行計算)。

通常在模組化中使用的投影函數有球形、圓柱、以及平面投影,也可以選其他一些輸入作為投影函數。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖4 不同的紋理坐标,上面一行從左到右分别為球形、圓柱、平面,以及自然uv投影:下面一行所示為把不同的投影運用于同一個物體的情形。

非互動式渲染器(Noninteractive renderers)通常将這些投影方程稱為渲染過程本身的一部分。一個單獨的投影方程就有可能适用于整個模型,但其實實際上,美術同學不得不使用各種各樣的工具将模型進行分割,針對不同的部分,分别使用不同的投影函數。如圖5所示。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

                                       圖5 使用不同的投影函數将紋理以不同的方式投射到同一個模型上

各種常見投影的不同要點:

  • 球形投影(The spherical projection)。球形投影将點投射到一個中心位于某個點的虛拟球體上,這個投影與Blinn與Newell的環境貼圖方法相同。
  • 圓柱投影(Cylindrical projection)。與球體投影一樣,圓柱投影計算的是紋理坐标u,而計算得到的另一個紋理坐标v是沿該圓柱軸線的距離。這種投影方法對具有自然軸的物體比較适用,比如旋轉表面,如果表面與圓柱體軸線接近垂直時,就會出現變形。
  • 平面投影(The planar projection)。平面投影非常類似于x-射線幻燈片投影,它沿着一個方向進行投影,并将紋理應用到物體的所有表面上。這種方法通常使用正交投影,用來将紋理圖應用到人物上,其把模型看作一個用紙做的娃娃,将不同的紋理粘貼到該模型的前後。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
         圖6 雕塑模型上的多個較小紋理,儲存在兩個較大的紋理上。右圖顯示了多邊形網格如何展開并顯示在紋理上的。

2.2 映射函數 The Corresponder Function

映射函數(The Corresponder Function)的作用是将參數空間坐标(parameter-space coordinates)轉換為紋理空間位置(texture space locations)。

我們知道圖像會出現在物體表面的(u,v)位置上,且uv值的正常範圍在[0,1)範圍内。超出這個值域的紋理,其顯示方式便可以由映射函數(The Corresponder Function)來決定。

在OpenGL中,這類映射函數稱為“封裝模式(Warapping Mode)”,在Direct3D中,這類函數叫做“尋址模式(Texture Addressing Mode)”。最常見的映射函數有以下幾種:

  • 重複尋址模式,wrap (DirectX), repeat (OpenGL)。圖像在表面上重複出現。
  • 鏡像尋址模式,mirror。圖像在物體表面上不斷重複,但每次重複時對圖像進行鏡像或者反轉。
  • 夾取尋址模式,clamp (DirectX) ,clamp to edge (OpenGL)。夾取紋理尋址模式将紋理坐标夾取在[0.0,1.0]之間,也就是說,在[0.0,1.0]之間就是把紋理複制一遍,然後對于[0.0,1.0]之外的内容,将邊緣的内容沿着u軸和v軸進行延伸。
  • 邊框顔色尋址模式,border (DirectX) ,clamp to border (OpenGL)。邊框顔色尋址模式就是在[0.0,1.0]之間繪制紋理,然後[0.0,1.0]之外的内容就用邊框顔色填充。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

                          圖7 圖像尋址模式,從左到右分别是重複尋址、鏡像尋址、夾取尋址、邊框顔色尋址

需要注意,每個紋理軸可以使用不同的映射函數。例如在u軸使用重複尋址模式,在v軸使用夾取尋址模式。

叁 · 體紋理 Volume Texture

三維紋理(3D texture),即體紋理(volume texture),是傳統二維紋理(2D texture)在邏輯上的擴充。二維紋理是一張簡單的位圖圖檔,用于為三維模型提供表面點的顔色值;而一個三維紋理,可以被認為由很多張 2D 紋理組成,用于描述三維空間資料的圖檔。三維紋理通過三維紋理坐标進行通路 。

雖然體紋理具有更高的儲存要求,并且濾波成本更高,但它們具有一些獨特的優勢:

  • 使用體紋理,可以跳過為三維網格确定良好二維參數的複雜過程,因為三維位置可以直接用作紋理坐标,進而避免了二維參數化中通常會發生的變形和接縫問題。
  • 體紋理也可用于表示諸如木材或大理石的材料的體積結構。使用三維紋理實作出的這些模型,看起來會很逼真,渾然天成。
劣勢:
  • 使用體紋理作為表面紋理會非常低效,因為三維紋理中的絕大多數樣本都沒起到作用。

肆 · 立方體貼圖 Cube Map

立方體紋理(cube texture)或立方體貼圖(cube map)是一種特殊的紋理技術,它用6幅二維紋理圖像構成一個以原點為中心的紋理立方體,這每個2D紋理是一個立方體(cube)的一個面。對于每個片段,紋理坐标(s, t, r)被當作方向向量看待,每個紋素(texel)都表示從原點所看到的紋理立方體上的圖像。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
    圖8 Cube Map圖示1
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖9 Cube Map圖示2

可以使用三分量紋理坐标向量來通路立方體貼圖中的資料,該矢量指定了從立方體中心向外指向的光線的方向。選擇具有最大絕對值的紋理坐标對應的相應的面。(例如:對于給定的矢量(−3.2, 5.1, −8.4),就選擇-Z面),而對剩下的兩個坐标除以最大絕對值坐标的絕對值,即8.4。 那麼就将剩下的兩個坐标的範圍轉換到了-1到1,然後重映射到[0,1]範圍,以友善紋理坐标的計算。例如,坐标(-3.2,5.1)映射到((-3.2 / 8.4 + 1)/ 2,(5.1/ 8.4 + 1)/ 2)≈(0.31,0.80)。

立方體貼圖支援雙線性濾波以及mip mapping,但問題可以可能會在貼圖接縫處出現。有一些處理立方體貼圖專業的工具在濾波時考慮到了可能的各種因素,如ATI公司的CubeMapGen,采用來自其他面的相鄰樣本建立mipmap鍊,并考慮每個紋素的角度範圍,可以得到比較不錯的效果。如圖10。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖10 立方體貼圖過濾。最左邊兩個圖像使用2 x 2和4 x 4的立方體貼圖的紋理層次,采用标準立方體貼圖生成mipmap鍊。因接縫顯而易見,除了極端細化的情況,這些mipmap級别并不可用。兩個最右邊的圖像使用相同分辨率的mipmap級别,通過在立方體面和采用角度範圍進行采樣生成。 由于沒有接縫,不易失真,這些mipmap甚至可以用于顯示在很大的螢幕區域的對象。

伍 · 紋理緩存 Texture Caching

一個複雜的應用程式可能需要相當數量的紋理。快速紋理存儲器的數量因系統而異,但你會發現它們永遠不夠用。有各種各樣的紋理緩存(texture caching)技術,但我們一直在上傳紋理到記憶體的開銷和紋理單次消耗的記憶體量之間尋求一個好的平衡點。比如,一個由紋理貼圖的多邊形對象,初始化在離相機很遠的位置,程式也許會隻加載mipmap中更小的子紋理,就可以很完美的完成這個對象的顯示了。

一些基本的建議是——保持紋理在不需要放大再用的前提下盡可能小,并嘗試基于多邊形将紋理分組。即便所有紋理都一直存儲在記憶體中,這種預防措施也可能會提高處理器的緩存性能。

以下是一些常見的紋理緩存使用政策:

5.1 最近最少使用政策(Least Recently Used ,LRU)

最近最少使用(Least Recently Used ,LRU)政策是紋理緩存方案中常用的一種政策,其作用如下。加載到圖形加速器的記憶體中的每個紋理都被給出一個時間戳,用于最後一次通路以渲染圖像時。當需要空間來加載新的紋理時,首先解除安裝最舊時間戳的紋理。一些API還允許為每個紋理設定一個優先級:如果兩個紋理的時間戳相同,則優先級較低的紋理首先被解除安裝。 設定優先級可以幫助避免不必要的紋理交換。

5.2 最近最常使用政策(Most Recently Used,MRU)

如果開發自己的紋理管理器,Carmack(就是那個遊戲界大名鼎鼎的卡馬克)提出了一種非常有用的政策,也就是對交換出緩沖器的紋理進行核查 [具體可見原書參考文獻374]。大概思想是這樣:鑒于如果在目前幀中載入紋理,會發生抖動(Thrashing)的情況。這種情況下,LRU政策是一種非常不好的政策,因為在每幀畫面中會對每張紋理圖像進行交換。在這種情況下,可以采用最近最常使用(Most Recently Used,MRU)政策,直到在畫面中沒有紋理交換時為止,再然後切換回LRU。

5.3 預取政策(Prefetching)

加載紋理花費顯着的時間,特别是在需将紋理轉換為硬體原生格式時。 紋理加載在每個架構可以有很大的不同。在單個幀中加載大量紋理使得難以保持恒定的幀速率。一種解決方案是使用預取(prefetching),在将來需要預期的情況下,預計未來的需求然後加載紋理,将加載過程分攤在多幀中。

5.4 裁剪圖政策(Clipmap)

對于飛行模拟和地型模拟系統,圖像資料集可能會非常巨大。傳統的方法是将這些圖像分解成更小的硬體可以處理的瓦片地圖(tiles)。Tanner等人提出了一種稱為裁剪圖(clipmap)的改進資料結構。其思想是,将整個資料集視為一個mipmap,但是對于任何特定視圖,隻需要mipmap的較低級别的一小部分即可。支援DirectX 10的GPU就能夠實作clipmap技術。用這種技術制作的圖像如圖11所示。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖11 高分辨率地形圖通路海量圖像資料庫。使用clipmapp技術可以減少在同一時間所需資料量。

陸 · 紋理壓縮 Texture Compression

直接解決記憶體和帶寬問題和緩存問題的一個解決方案是固定速率紋理壓縮(Fixed-rateTexture Compression)。通過硬體解碼壓縮紋理,紋理可以需要更少的紋理記憶體,進而增加有效的高速緩存大小。至少這樣的紋理使用起來更高效,因為他們在通路時消耗更少的記憶體帶寬。

有多種圖像壓縮方法用于圖像檔案格式,如JPEG和PNG,但在硬體上對其實作解碼會非常昂貴。S3公司開發一種名為S3紋理壓縮(S3 Texture Compression,S3TC)的方法,目前已經被選為DirectX中的标準壓縮模式,稱為DXTC。在DirectX 10中,這種方法稱為BC (Block Compression)。其優點是建立了一個固定大小,具有獨立的編碼片段,并且解碼簡單,同時速度也很快。每個壓縮部分的圖像可以獨立處理,沒有共享查找表(look-up tables)或其他依賴關系,這同樣地簡化了解碼過程。

還有幾種S3/DXTC/BC壓縮方案的變種存在,他們有一些共同的特征。把紋理按4x4個單元(紋素)大小劃分為塊。每個塊對應一張四色查找表,表中存有兩個标準RGB565格式表示的16位顔色,另外使用标準插入算法在插入兩個新的顔色值,由此構成四色查找表。4x4大小的紋理塊中每個單元(像素點)用兩個bit表示,每一個都代表四色查找表中的一種顔色。可以看出,實質上是利用每個單元(像素點)中的兩個bit來索引四色查找表中的顔色值。

這些壓縮技術可以應用于立方體或體積圖,以及二維紋理。而其主要缺點是它們是有損的壓縮。 也就是說,原始圖像通常不能從壓縮版本檢索。 僅使用四個或八個内插值來表示16個像素。 如果一個瓦片貼圖有更大的數值,相較壓縮前就會有一些損失。 在實踐中,如果正常使用這些壓縮方案,一般需給出可接受的圖像保真度。

DXTC的一個問題是用于塊的所有顔色都位于RGB空間的直線上。例如,DXTC不能在一個塊中同時表示紅色,綠色和藍色。

下面對幾種不同紋理壓縮變體(S3/DXTC/BC以及ETC)在編碼上的異同點分節概述。

6.1 DXT1

DXT1(DirectX 9.0)或BC1(DirectX 10.0及更高版本) - 每個塊具有兩個16位參考RGB值(5位紅,6綠,5藍)的紋素,而每個紋素具有2位插值因子,以便從一個參考值或兩個中間值之間選擇。DXT1作為五種變體中最精簡的版本,塊占用為8個位元組,即每個紋素占用4位。 與未壓縮的24位RGB紋理相比,有着6:1的紋理壓縮率。

6.2 DXT3

DXT3(DirectX 9.0)或BC2(DirectX 10.0及更高版本) - 每個塊都具有與DXT1塊相同的RGB資料編碼。另外,每個紋素都具有單獨存儲4位alpha值(這是唯一的直接存儲資料的形式,而不是用插值的形式)。DXT3塊占用16個位元組,或每個紋理元素8位。與未壓縮的32位RGBA紋理相比,有着4:1的紋理壓縮率。

6.3 DXT5

DXT5(DirectX 9.0)或BC3(DirectX 10.0及更高版本) - 每個塊都具有與DXT1塊相同的RGB資料編碼。此外,alpha資料使用兩個8位參考值和一個每紋素3位的插值因子進行編碼。每個紋素可以選擇參考alpha值之一或六個中間值之一作為其值。DXT5塊具有與DXT3塊相同的存儲要求,也就是DXT3塊占用16個位元組,即每個紋理元素8位。與未壓縮的32位RGBA紋理相比,有着4:1的紋理壓縮率。

6.4 ATI1

ATI1(ATI公司的特定擴充名)或BC4(DirectX 10.0及更高版本)- 每個塊存儲單個顔色的資料通道,以與DXT5中的alpha資料相同的方式進行編碼。 BC4塊占用8個位元組,即每個紋素占用4位。與未壓縮的8位單通道紋理相比,有着4:1的紋理壓縮率。僅在較新的ATI的硬體或任意供應商的DirectX 10.0硬體上才支援此格式。

6.5 ATI2

ATI2(ATI公司的特定擴充名,也稱為3Dc)或BC5(DirectX10.0及更高版本) - 每個塊存儲兩個顔色通道的資料,以與BC4塊或DXT5中的alpha資料相同的方式進行編碼。 BC5塊占用16個位元組,即每個紋理元素8位。與未壓縮的16位雙通道紋理相比,有着4:1的紋理壓縮率。也僅在較新的ATI的硬體或任意供應商的DirectX 10.0硬體上才支援此格式。

6.6 ETC

對于OpenGL ES,選擇了另一種稱為ETC(Ericsson tex- ture compressio,ETC)的壓縮算法。方案與S3TC具有相同的特點,即快速解碼,随機通路,無間接查找,速率固定。ETC算法将4×4紋素的塊編碼為64位,即每個紋理元素4位。基本思想如圖12所示。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖12  ETC算法對像素塊的顔色進行編碼,然後修改每像素的亮度以建立最終的紋理顔色

每個2×4塊(或4×2,取決于哪個品質更佳)存儲基本顔色。每個塊還從一個小的靜态查找表中選擇一組四個常量,并且塊中的每個紋素可以選擇在標明的查找表中添加一個值,添加的這個值就可以是每像素的亮度。

也可以這樣了解:ETC壓縮算法将圖像中的chromatic和luminance分開存儲的方式,而在解碼時使用luminance對chromatic進行調制進而重制原始圖像資訊。

兩個要點:

  • ETC的圖檔壓縮的品質和DXTC相當。
  • ETC也主要有兩種方法:ETC1和改進後的ETC2。

柒 · 程式貼圖紋理 Procedural Texturing

程式貼圖紋理(Procedural Texturing,也可譯為過程紋理)是用計算機算法生成的,旨在建立用于紋理映射的自然元素(例如木材,大理石,花崗岩,金屬,石頭等)的真實表面或三維物體而建立的紋理圖像。通常,會使用分形噪聲(fractal noise)和湍流擾動函數(turbulence functions)這類“随機性”的函數來生成程式貼圖紋理。

給定紋理空間位置,進行圖像查找是生成紋理值的一種方法。另一種方法是對函數進行求值,進而得到一個程式貼圖紋理(procedural texture)。

過程紋理主要用于模拟自然界中常見的Marble,Stone,Wood,Cloud等紋理。大多數的過程紋理都是基于某類噪聲函數(Noise Function),比如說perlin noise。在過去,由于過程紋理計算量很大,在實時繪制中很少使用。但是GPU的出現,促進了過程紋理在實時渲染中的廣泛應用。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖13 程式貼圖紋理示例

程式貼圖紋理通常用于離線渲染應用程式,而圖像紋理在實時渲染中更為常見。這是由于在現代GPU中的圖像紋理硬體有着極高效率,其可以在一秒鐘内執行數十億個紋理通路。然而,GPU架構正在朝着更便宜的計算能力和(相對)更昂貴的存儲器通路而發展。這将使程式紋理在實時應用程式中更常見,盡管它們不可能完全替代圖像紋理。

考慮到體積圖像紋理的高存儲成本,體積紋理是用于程式貼圖紋理是一項特别有吸引力的應用。這樣的紋理可以通過各種技術來合成,最常見的是使用一個或多個噪聲函數來産生紋理的值。

捌 · 凹凸貼圖與其改進

凹凸貼圖(Bump Mapping)思想最早是由圖形學屆大牛中的大牛Jim Blinn提出,後來的Normal Mapping,Parallax Mapping,Parallax Occulision Mapping,Relief Mapping等等,均是基于同樣的思想,隻是考慮得越來越全面,效果也越來越逼真。

以下是幾種凹凸貼圖與其改進方法的總結對比。除了Displacement Mapping方法以外,其他的幾種改進一般都是通過修改每像素着色方程來實作,關鍵思想是通路紋理來修改表面的法線,而不是改變光照方程中的顔色分量。物體表面的幾何法線保持不變,我們修改的隻是照明方程中使用的法線值。他們比單獨的紋理有更好的三維感官,但是顯然還是比不上實際的三維幾何體。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
以下是各個方法分别的原理和特性說明。

8.1 凹凸貼圖 Bump Mapping

凹凸貼圖是指計算機圖形學中在三維環境中通過紋理方法來産生表面凹凸不平的視覺效果。它主要的原理是通過改變表面光照方程的法線,而不是表面的幾何法線,或對每個待渲染的像素在計算照明之前都要加上一個從高度圖中找到的擾動,來模拟凹凸不平的視覺特征,如褶皺、波浪等等。

Blinn于1978年提出了凹凸貼圖方法。使用凹凸貼圖,是為了給光滑的平面,在不增加頂點的情況下,增加一些凹凸的變化。他的原理是通過法向量的變化,來産生光影的變化,進而産生凹凸感。實際上并沒有頂點(即Geometry)的變化。

表示凹凸效果的另一種方法是使用高度圖來修改表面法線的方向。每個單色紋理值代表一個高度,是以在紋理中,白色表示高高度區域,黑色是低高度的區域(反之亦然)。示例如圖14。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖14  波浪高度凹凸貼圖以及其在材質上的使用

8.2 移位貼圖 Displacement Mapping

Displacement Mapping,移位貼圖,也有人稱為置換貼圖,或稱高度紋理貼圖(Heightfield Texturing)。這種方法類似于法線貼圖,移位貼圖的每一個紋素中存儲了一個向量,這個向量代表了對應頂點的位移。注意,此處的紋素并不是與像素一一對應,而是與頂點一一對應,是以,紋理的紋素個數與網格的頂點個數是相等的。在VS階段,擷取每個頂點對應的紋素中的位移向量,(注意,直到3.0版本的vs才支援紋理資料的擷取,之前的版本隻有ps才能擷取紋理資料),施加到局部坐标系下的頂點上,然後進行世界視點投影變換即可。

8.3 法線貼圖 Normal Mapping

法線貼圖(Normal mapping)是凸凹貼圖(Bump mapping)技術的一種應用,法線貼圖有時也稱為“Dot3(仿立體)凸凹紋理貼圖”。凸凹與紋理貼圖通常是在現有的模型法線添加擾動不同,法線貼圖要完全更新法線。與凸凹貼圖類似的是,它也是用來在不增加多邊形的情況下在濃淡效果中添加細節。但是凸凹貼圖通常根據一個單獨的灰階圖像通道進行計算,而法線貼圖的資料源圖像通常是從更加細緻版本的物體得到的多通道圖像,即紅、綠、藍通道都是作為一個單獨的顔色對待。

簡單來說,Normal Map直接将正确的Normal值儲存到一張紋理中去,那麼在使用的時候直接從貼圖中取即可。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖15 基于法線貼圖的凹凸映射,每個顔色通道實際上是表面法線坐标。紅色通道是x偏差; 紅色越多,正常點越多。 綠色是y偏差,藍色是z。 右邊是使用法線貼圖生成的圖像。 請注意立方體頂部的扁平外觀。

8.4 視差貼圖 Parallax Mapping

視差貼圖Parallax Mapping,又稱為 Offset Mapping,以及virtual displacement mapping),于2001年由Kaneko引入,由Welsh進行了改進和推廣。視差貼圖是一種改進的Bump Mapping技術,相較于普通的凹凸貼圖,視差貼圖技術得到凹凸效果得會更具真實感(如石牆的紋理将有更明顯的深度)。視差貼圖是通過替換渲染多邊形上的頂點處的紋理坐标來實作的,而這個替換依賴于一個關于切線空間中的視角(相對于表面法線的角度)和在該點上的高度圖的方程。簡單來說,Parallax Mapping利用Height Map進行了近似的Texture Offset。如圖 6.32。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖16 視差貼圖

8.5 浮雕貼圖 Relief Mapping

我們知道,Parallax Mapping是針對Normal Mapping的改進,利用HeightMap進行了近似的Texture Offset。而Relief Mapping是精确的Texture Offset,是以表現力上應該是比較完美的。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing

圖17 相較于視差貼圖(左),浮雕貼圖(右)可以實作更深的凹凸深度。

Parallax Mapping能夠提供比Bump Mapping更多的深度,尤其相比于小視角下,但是如果想提供更深的深度,Parallax Mapping就無能為力了,Relief Mapping則可以很好的勝任。

相較于Parallax Mapping,浮雕貼圖(Relief Mapping)可以實作更深的凹凸深度。浮雕貼圖方法不僅更容易提供更深的深度,還可以做出自陰影和閉塞效果,當然算法也稍稍有點複雜,具體細節可以參考這篇中文文獻:http://www.ixueshu.com/document/3dc4369a761ca0d6318947a18e7f9386.html,而如果要用一句話概括Relief Mapping,将會是:“在Shader裡做光線追蹤”。

【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖18 法線貼圖和浮雕貼圖的對比。法線貼圖不發生自遮擋。
【《Real-Time Rendering 3rd》 提煉總結】(五) 第六章 · 紋理貼圖及相關技術 The Texturing
圖19 浮雕貼圖,使石塊看起來更逼真

玖·其他參考

[1] https://learnopengl.com/#!Advanced-OpenGL/Cubemaps

[2] http://blog.csdn.net/pizi0475/article/details/6650855

[3] http://blog.csdn.net/bugrunner/article/details/50538770

[4] http://www.cnblogs.com/szlongman/archive/2005/11/17/278955.html

[5] https://zh.wikipedia.org/wiki/%E6%B3%95%E7%BA%BF%E8%B4%B4%E5%9B%BE

[6] http://www.ixueshu.com/document/3dc4369a761ca0d6318947a18e7f9386.html

[7] http://www.cnblogs.com/cxrs/archive/2009/11/22/1608086.html

繼續閱讀