在計算機圖形學中,紋理濾波(Texture filtering)是一種針對一個使用材質貼圖的像素,使用臨近的一個或多個紋素計算其紋理顏色的方法。從數學上來說,紋理濾波是抗鋸齒的一種,但它更著重於濾掉紋理中的高頻,而不像其他抗鋸齒技術那樣著重於改善邊界顯示效果。簡單來說,它使得同一個紋理可以被用於不同的形狀,尺寸和角度,同時儘可能減少顯示時的模糊和閃爍。
在應用紋理貼圖時,需要對於每一個像素中心所在的位置進行查詢紋理值的操作。但是由於被渲染的目標表面相對於視角,可能處於任意距離或者角度,一個像素不一定有一個紋素對應。所以需要應用某種濾波方式來決定其紋理值,缺少濾波或使用不當都會造成最終的圖像存在例如鋸齒和閃爍之類的瑕疵。
由於應用紋理貼圖的表面相對於視角的距離和角度不同,在表面之上的一個像素和對應的紋理之上一個或多個紋素之間可能存在多種對應關係,這也導致需要 應用不同的濾波方式。如果把一個正方形的紋理映射到一個正方形的表面上,在離視角的某一個距離上,螢幕上的一個像素和一個紋素幾乎等尺寸。如果比這個距離近,紋素就會比像素尺寸大,這是就需要將紋素相應地放大,這就是所謂的紋理放大。同理,如果比這個距離遠,紋素將比像素尺寸小,一個像素最終的紋理值就會從其覆蓋的多個紋素的值計算出,這也就是通常所說的紋理縮小。常見的圖像應用程序介面,例如OpenGL,提供了多種的縮小和放大濾波方式。
值得注意的是,即使在像素和紋素尺寸相等的情況下,其之間也不一定就存在一一對應的關係。例如可能存在錯位而導致一個像素覆蓋了相鄰四個紋素的各一部分。所以仍然需要某種濾波方式。
此議題的選擇對應計算量是一個高階選項,因此不要考慮太多,先用雙線性濾波(Bilinear filtering)就好了。
最近鄰插值(Nearest-neighbor interpolation)
最近鄰插值是最快速,也是最粗糙的濾波方式。最鄰近像素中心的紋素顏色將被作為像素的顏色。在紋理放大時,這種方式會導致色塊;而在紋理縮小時,則會導致閃爍和鋸齒。最近鄰Mipmapping(Nearest-neighbor with mipmapping)
這種方式先根據距離選擇最近的mipmap層級,再從其中選擇最靠近像素中心的紋素。這對閃爍和鋸齒很有效,但不能減少色塊。雙線性濾波(Bilinear filtering)
雙線性濾波會從最近的mipmap層次上,選擇最靠近像素中心的四個紋素,再根據他們靠近像素中心的具體進行權重插值。這時如果進行紋理放大,當像素相對於紋素移動時,像素顏色會從逐漸從一個紋素顏色變化到相鄰的紋素顏色,而不是像最近鄰插值那樣,在穿過兩個紋素的邊界時發生突變,這樣就消除色塊。雙線性濾波經常與mipmapping一起使用,但也可以單獨使用,但這時會出現閃爍和鋸齒化的問題。一般來說,因為 bilinear interpolation 的效果已經相當不錯,再加上計算量又少,所以一般 3D 顯示晶片都是使用 bilinear interpolation 來處理貼圖的重新取樣問題,特別是在放大的部分。
三線性濾波(Trilinear filtering)
在使用mipmapping雙線性濾波時,當目標表面的距離變化時,會從一個mipmap層次突變到相鄰的層次。三線性濾波被用來解決這個問題,方法是在最相鄰的兩個mipmap層次上分別進行雙線性濾波,再用得到的兩個值進行線性插值。值得注意的是,當距離小於mipmap的零層次時(即紋素大小 超過像素大小時),三線性插值退化為雙線性插值。各向異性濾波(Anisotropic filtering)
各向異性過濾是 現有消費級顯示卡所提供的圖像質量最佳的濾波方式。傳統的各項同性濾波中只是在正方形的mipmap層次間進行雙線性或三線性插值,但是當一個目標表面和 攝像機之間角度較大時,紋理的填充面積並不是正方形,這樣便引入了模糊和閃爍等瑕疵。 於是,各向異性濾波需要對一個非方形紋理進行採樣。在一些簡單的實現中,顯示卡使用長方形的紋理取代方形紋理,達到了較好的近似效果。但是這種方式在處理 邊界時效果依然不理想,原因是在傾斜的表面上,近端邊界比遠端邊界擁有更多的像素。於是一些高端顯示卡使用了梯形紋理,當然這也要求更大的運算量。因此在OPENGL1.x中提供一個檢查的機制指令,來確認其最大運算能力。
float degree;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, °ree);
在OpenGL里面使用各異向性紋理過濾首先要系統運行的OpenGL實現支持EXT_texture_filter_anisotropic 這個OpenGL擴展。
OpenGL里面的各異向性紋理過濾的參數設置是獨立于紋理縮小和放大這兩種情況的,也就是說不需要為這兩種情況進行分別設置。參數設置十分簡單,只有一個參數就是最大各異向程度(TEXTURE_MAX_ANISOTROPY_EXT)。因為紋理縮放的各異向程度越大,就需要對更多的紋理單元進行采樣,這樣在處理速度上是不可接受的,所以必須設置一個最大各異向程度,當OpenGL進行各異向性過濾的時候,采用的各異向程度參數為紋理縮放的各異向程度和最大各異向程度之間的最小值,也就是說當紋理縮放的各異向程度大于設置的最大各異向程度時,將使用設置的最大各異向程度作為過濾使用的參數。顯然可見,當該參數設置為1的時候就是不進行各異向性過濾,1也是OpenGL為這個參數設定的缺省設置。
下面是一段示例程序:
//假設這是一個二維紋理并且已經設置了mipmap
//獲得運行的OpenGL實現支持的最大各異向程度
Glfloat largest_supported_anisotropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,
&largest_supported_anisotropy);
//設置紋理縮小時采用的過濾方法,這里設置的是三線性過濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
//設置紋理放大時采用的過濾方法,這里設置的是線性過濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
//用OpenGL實現支持的最大各異向程度設置最大各異向程度參數
glTexParameterf(GL_TEXTURE_MAX_ANISOTROPY_EXT,
largest_supported_anisotropy);
原始圖片
雙線性濾波(Bilinear filtering)
OPENGLES指令
使用GL_TEXTURE_MIN_FILTER,用在貼圖區大於貼圖元素。有六種選項可用。
1. GL_NEAREST
2. GL_LINEAR
3. GL_NEAREST_MIPMAP_NEAREST
4. GL_LINEAR_MIPMAP_NEAREST
5. GL_NEAREST_MIPMAP_LINEAR (default)
6. GL_LINEAR_MIPMAP_LINEAR
使用GL_TEXTURE_MAG_FILTER,用在貼圖區域小於或等於貼圖元件。有兩種選項可用。
1. GL_NEAREST
2. GL_LINEAR (default)
範例
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
參考網頁
http://zh.wikipedia.org/wiki/%E7%BA%B9%E7%90%86%E6%BB%A4%E6%B3%A2
http://www.opengpu.org/forum.php?mod=viewthread&tid=100
http://book.51cto.com/art/201208/352655.htm
指令使用說明
http://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexParameter.xml
http://www.cs.nccu.edu.tw/~mtchi/3d12/lab/3d12-lab5.pdf
http://www.informit.com/articles/article.aspx?p=770639&seqNum=2
http://big5.china-code.net/ap-ccfmFMLu4k-9346.html

沒有留言:
張貼留言