計算機圖形學-線性過濾

weixin_33895657發表於2018-07-19

紋理過濾

1. 為什麼在紋理取樣時需要texture filter(紋理過濾)。

我們的紋理是要貼到三維圖形表面的,而三維圖形上的pixel中心和紋理上的texel中心並不一至(pixel不一定對應texture上的取樣中心texel),大小也不一定一至。當紋理大於三維圖形表面時,導至一個畫素被對映到許多紋理畫素上;當維理小於三維圖形表面時,許多個畫素都對映到同一紋理。

當這些情況發生時,貼圖就會變得模糊或發生錯位。要解決此類問題,必須通過技術平滑texel和pixel之間的對應。這種技術就是紋理濾波。

不同的過濾模式,計算複雜度不一樣,會得到不同的效果。過濾模式由簡單到複雜包括:Nearest Point Sampling(最近點取樣),Bilinear(雙線性過濾)、Trilinear(三線性過濾)、Anisotropic Filtering(各向異性過濾)。

在瞭解這些之前,有必要了解什麼是多級紋理貼圖(MipMap)和什麼是各向同性,各向異性。

2. 什麼是MipMap?

Mipmap由Lance Williams 在1983的一篇文章“Pyramidal parametrics”中提出。Wiki中有很詳細的介紹(http://en.wikipedia.org/wiki/Mipmap ) . 比如一張256X256的圖,在長和寬方向每次減少一倍,生成:128X128,64X64,32X32,16X16,8X8,4X4,2X2,1X1,八張圖,組成MipMap,如下圖示。

13145841-ade9db1a2d3dbf6c.jpg

Mipmap早已被硬體支援,硬體會自動為建立的Texture生成mipmap的各級。在D3D的API:CreateTexture中有一個引數levels,就是用於指定生成mipmap到哪個級別,當不指定時就一直生成到1X1。

3. 什麼是各向同性和各向異性?

當需要貼圖的三維表面平行於螢幕(viewport),則是各向同性的。當要貼圖的三維表面與螢幕有一定角度的傾斜,則是各向異性的。

也可以這樣理解,當一個texture貼到三維表面上從Camera看來沒有變形,投射到螢幕空間中後U方向和V方向比例仍然是一樣的,便可以理解成各向同性。反之則認為是各向異性。

4. Nearest Point Sampling(最近點取樣)

這個最簡單,每個畫素的紋理座標,並不是剛好對應Texture上的一個取樣點texel,怎麼辦呢?最近點取樣取最接近的texel進行取樣。

當紋理的大小與貼圖的三維圖形的大小差不多時,這種方法非常有效和快捷。如果大小不同,紋理就需要進行放大或縮小,這樣,結果就會變得矮胖、變形或模糊。

5. Bilinear(雙線性過濾)

雙線性過濾以pixel對應的紋理座標為中心,採該紋理座標周圍4個texel的畫素,再取平均,以平均值作為取樣值。

雙線性過濾畫素之間的過渡更加平滑,但是它只作用於一個MipMap Level,它選取texel和pixel之間大小最接近的那一層MipMap進行取樣。當和pixel大小匹配的texel大小在兩層Mipmap level之間時,雙線性過濾在有些情況效果就不太好。於是就有了三線性過濾。

6. Trilinear(三線性過濾)

三線性過濾以雙線性過濾為基礎。會對pixel大小與texel大小最接近的兩層Mipmap level分別進行雙線性過濾,然後再對兩層得到的結果進生線性插值。

三線性過濾在一般情況下效果非常理想了。但是到目前為止,我們均是假設是texture投射到螢幕空間是各向同性的。但是當各向異性的情況時,效果仍然不理想,於是產生了Anisotropic Filtering(各向異性過濾)。

7. Anisotropic Filtering(各向異性過濾)

先看效果,左邊的圖採用三線性過濾,右邊的圖採用各向異性過濾。

13145841-a8d46417940894f4.jpg

各向同性的過濾在取樣的時候,是對正方形區域裡行取樣。各向異性過濾把紋理與螢幕空間的角度這個因素考慮時去。簡單地說,它會考濾一個pixel(x:y=1:1)對應到紋理空間中在u和v方向上u和v的比例關係,當u:v不是1:1時,將會按比例在各方向上取樣不同數量的點來計算最終的結果(這時取樣就有可能是長方形區域)。

我們一般指的Anisotropic Filtering(AF)均是基於三線過濾的Anisotropic Filtering,因此當u:v不為1:1時,則Anisotropic Filtering比Trilinear需要取樣更多的點,具體要採多少,取決於是多少X的AF,現在的顯示卡最多技持到16X AF。

當開啟16X AF的時候,硬體並不是對所有的texture取樣都用16X AF,而是需要先計算螢幕空間與紋理空間的夾角(量化後便是上面所說的u:v),只有當夾角大到需要16X時,才會真正使用16X.

如果想了解AF的實現原理,可以查閱此篇Paper: “Implementing an anisotropic texture filter”. 現在AF都是硬體實現,因此只有少數人才清楚AF的具體實現,也可以由Pixel Shader來實現AF,當然效能遠不如使用硬體來完成。

8. 各過濾模式效能比較。

下表是各種過濾模式採一個pixel需要sample的次數:

型別取樣數

Nearest Point Sampling1

Bilinear4

Trilinear8

Anisotropic Filtering 4X32

Anisotropic Filtering 16X128

一般而言,取樣數越多,效果最好,但具體使用時要綜合考慮效能。

DirectX11 過濾器

1. 倍增(magnification)現象

紋理貼圖元素應該被視為在一個連續影像上的離散顏色取樣;不應該被視為矩形區域。那麼問題是:當我們指定的紋理座標(u,v)與任何一個紋理元素點都不對應時會產生什麼結果?這一問題會發生在如下情景中:當觀察點離場景中的一面牆很近時,牆會被放大,以至於會蓋住整個螢幕。如果顯示器的解析度為1024×1024,牆體紋理的解析度為256×256,那麼就會出現倍增(magnification)問題——我們將要用很少的紋理元素來覆蓋很多的畫素。在本例中,每個紋理元素要覆蓋4個畫素。當頂點紋理座標在三角形表面上進行插值時,每個畫素都會得到一對唯一的紋理座標。所以,畫素的紋理座標不會與任何一個紋理元素點對應。 我們可以使用插值方法來估算紋理元素之間的顏色。圖形硬體提供了兩種插值方法:常量插值和線性插值。線性插值是我們最常用的插值方法。

(1). 1D過濾 

下圖說明c在1D空間中的插值方法:假設有一個包含256個取樣點的1D紋理以及一個插值紋理座標u = 0.126484375。那該紋理座標對應的紋理元素為0.126484375×256 = 32.38。當然,這個值位於兩個紋理取樣點之間,我們必須使用插值來估算它。

13145841-1369f3031b6f3fd5.jpg

(a)給出紋理元素點,我們構造一個分段常量函式來估算紋理元素點之間的值;這種方法有時也稱為最近鄰接點取樣(nearest neighbor point sampling),因為它總是用最近的紋理元素點的值作為取樣結果。(b)給出紋理元素點,我們構造一個分段線性函式來估算紋理元素點之間的值。

(2). 2D過濾 

2D線性插值也稱為雙線性插值(bilinear interpolation),如下圖所示。給出一對位於4個紋理元素之間的紋理座標,我們在u方向上進行兩次1D線性插值,然後在v方向上進行一次1D線性插值。

13145841-d1d480f5b5df3d3a.jpg

(這裡有4個紋理元素點cij、ci,j+1,ci+1,j、ci+1,j+1。我們想要估算c點的顏色,它位於這4個紋理元素點之間。在本例中,c位於cij右側0.75單位、cij下方0.38單位處。我們先在上面的兩個顏色之間進行1D線性插值得到cT。然後,在下面的兩個顏色之間進行1D線性插值得到cB。最後,在cT和cB之間進行線性插值得到c。)

(3). 常量插值與線性插值的區別 

下圖說明了常量插值和線性插值之間的區別。可以看到,常量插值會使影像出現明顯的塊狀。而線性插值較為平滑,但是與真實資料(例如,一幅高解析度的紋理)相比,通過插值得到的衍生資料仍然不夠理想。


13145841-4b22138b0c9745c2.jpg

(我們在一個立方體放大一幅板條箱紋理,使倍增問題出現。左圖使用常量插值,可以看到它產生了明顯的斑塊;這很容易理解,因為插值函式是離散的(第一幅圖a),它所形成的顏色過渡顯得生硬而不平滑。右圖使用線性插值,由於插值函式是連續的,所以它產生的影像較為平滑。)

需要強調的是,由於在互動式3D程式中觀察點的位置可以自由移動,所以我們對於倍增問題沒有一種非常徹底的解決辦法。在一定距離內,紋理可以有較好的效果,但是當觀察點與物體之間的距離越來越近時,效果會急轉直下。使用更高解析度的紋理可以緩解一問題。

注意:在紋理對映的環境下,使用常量插值來求解紋理元素之間的顏色值的過程也稱為點過濾(point filtering),使用線性插值來求解紋理元素之間的顏色值的過程也稱為線性過濾(linear filtering)。點過濾和線性過濾是Direct3D使用的術語。

2. 縮減(minification)現象

縮減(minification)與倍增的情況恰好相反。在縮減中,較多的紋理元素會被對映為較少的畫素。例如,考慮下面的情景:我們將一幅256×256的紋理對映到牆體上。然後把觀察點對準牆體,並向後移動觀察點,使牆體逐漸變小,直到牆體在螢幕上只佔64×64的畫素區域為止。現在,我們要把256×256個紋理元素對映為64×64個螢幕畫素。在這一情景中,畫素的紋理座標不會與紋理貼圖中的任何一個紋理元素對應。常量和線性插值過濾器仍然適用於縮減情況。不過,縮減的處理工作稍多一些。簡單的講,我們要把256×256個紋理元素均勻地縮減為64×64個紋理元素。多級漸近貼圖對映(mipmapping)為這一工作提供了一種高效的估值手段,只是要額外佔用一些記憶體。在初始化時(或建立資源時),通過對影像進行降階取樣生成紋理的多個縮略版本來建立多級漸近紋理鏈(mipmap chain,參見下圖)。求平均值的工作是根據多級漸近貼圖的大小提前計算出來的。在執行時,圖形硬體會根據程式設計師指定的多級漸近貼圖引數執行兩種不同的操作:

1.為紋理對映挑選一個與螢幕幾何體解析度最匹配的多級漸近紋理層,根據需要在多級漸近紋理層上使用常量插值或線性插值。這種用於多級漸近紋理的操作稱為點過濾(point filtering),因為它與常量插值很像——它只為紋理對映挑選一個最接近的多級漸近紋理層。

2.為紋理對映挑選兩個與螢幕幾何體解析度最匹配的多級漸近紋理層(其中,一個比螢幕幾何體解析度大一些,另一個比螢幕幾何體解析度小一些)。然後,在這兩個多級漸近紋理層上使用常量插值或線性插值,分別取出一個紋理顏色。最後,在這兩個紋理顏色之間進行插值。這種用於多級漸近紋理的操作稱為線性過濾(linear filtering),因為它與線性插值很像——它在兩個最匹配的多級漸近紋理層之間進行線性插值。

13145841-98966b2b53ae3f0b.jpg

(多級漸近紋理鏈;每個後續多級漸近紋理層的尺寸都是前一層的1/2,紋理層的下限尺寸是1×1。)

通過在多級漸近紋理鏈中選擇最佳紋理層,可以使縮減操作的總開銷降至最低。

3. 如何建立多級漸近紋理?

多級漸近紋理層即可以由美術師手工建立,也可以由過濾演算法生成。

DDS影像格式(DirectDraw Surface格式)可以直接把多級漸近紋理層儲存在檔案中;在這種情況下,只需要簡單的讀入資料——不需要在執行執行任何與多級漸近紋理層相關的演算法。DirectX紋理工具可以為紋理生成多級漸近紋理鏈,並匯出DDS檔案。當一個影像檔案不包含完整的多級漸近紋理鏈時,函式D3DX11CreateShaderResourceViewFromFile或D3DX11CreateTextureFromFile會使用指定的過濾演算法建立一個多級漸近紋理鏈(請參閱 SDK文件中D3DX11_IMAGE_LOAD_INFO,尤其是要注意MipFilter資料成員的描述)。我們可以看到,多級漸近紋理對映基本上是自動的。當資原始檔不包含多級漸近紋理鏈時,D3DX11會為我們自動生成一個紋理鏈。只要啟用了多級漸近紋理對映,硬體就會在執行時自動選擇正確的多級漸近紋理層。

注意:有時通用的過濾演算法可能會丟失你想要保留的細節。例如,在上面的那幅圖中,木板上的文字“Direct3D”在最低等級的漸進紋理中非常模糊。如果這不可接受,美工就需要手動建立/調整漸進層次以保留重要的細節。

4. 什麼是各向異性過濾?

我們還可以使用各向異性過濾(anisotropic filter)。當多邊形的法線向量與攝像機的觀察向量夾角過大時(例如,當多邊形垂直於觀察視窗時),這種過濾可以有效緩解影像的失真問題。只是它的資源佔用量較大。不過,當你需要對失真進行校正時,這些消耗是值得的。下圖是對各向異性過濾和線性過濾的一個比較。


13145841-6bb95ed15e249f8e.jpg

板條箱的頂面幾乎垂直於觀察視窗。(左圖)使用線性過濾,板條箱的頂面顯得極其模糊。(右圖)在同樣的角度上,使用各向異性過濾得到的渲染結果要好很多。

文章轉載自:https://blog.csdn.net/sinat_24229853/article/details/48880301

相關文章