Android OpenGL ES(七)----理解紋理與紋理過濾

1.理解紋理

 

OpenGL中的紋理能夠用來表示圖像,照片,甚至由一個數學算法生成的分形數據。每一個二維的紋理都由許多小的紋理元素組成,它們是小塊的數據,相似於咱們前面討論過的片斷和像素。要使用紋理,最經常使用的方式是直接從一個圖像文件加載數據。算法

 

每一個二維紋理都有其本身的座標空間,其範圍是從一個拐角的(00)到另外一個拐角的(11)。按照慣例,一個維度叫作S,而另外一個稱爲T。當咱們想要把一個紋理應用於一個三角形或一組三角形的時候,咱們要爲每一個頂點指定一組ST紋理座標,以便OpenGL知道須要用那個紋理的哪一個部分畫到每一個三角形上。這些紋理座標有時也會被稱爲UV紋理座標。如圖:緩存



圖1  OpenGL二維紋理座標優化

 

對一個OpenGL紋理來講,它沒有內在的方向性,所以咱們可使用不一樣的座標把它定向到任何咱們喜歡的方向上。然而,大多數計算機圖像都有一個默認的方向,它們一般被規定爲Y軸向下,Y的值隨着向圖像的底部移動而增長。只要咱們記住,若是想用正確的方向觀察圖像,那紋理座標就必需要考慮這點,這就不會給咱們帶來任何麻煩。spa

 

在標準OpenGL ES 2.0中,紋理沒必要是正方形,可是每一個維度都應該是2的冪(POT)。這就意味着每一個維度都是這樣的一個數字,如128256512等。這樣規定的緣由在於非POT紋理能夠被使用的場合很是有限,而POT紋理使用於各類狀況。內存

 

紋理的尺寸也有一個最大值,它根據不一樣的實現而變化,可是一般都比較大,好比2048*2048ci

 


2.理解紋理過濾

 


當紋理的大小被擴大或者縮小時,咱們還須要使用紋理過濾明確說明會發生什麼。當咱們在渲染表面上繪製一個紋理時,那個紋理的紋理元素可能沒法精確地映射到OpenGL生成的片斷上。有兩種狀況:縮小和放大。當咱們盡力把幾個紋理元素擠進一個片斷時,縮小就發生了;當咱們把一個紋理元素擴展到許多片斷時,方法就發生了。針對每一種狀況,咱們能夠配置OpenGL使用一個紋理過濾器。數學

 

首先,講述兩個基本的過濾模式:最近鄰過濾和雙線性插值。還有其餘的過濾模式,之後的博文會講解。咱們會使用下面的圖像闡述每一種過濾模式。it




 

最近鄰過濾table

 

這個方式爲每一個片斷選擇最近的紋理元素。當咱們放大紋理時,它的鋸齒效果看起來至關明顯,以下圖所示。擴展




 

每一個紋理單元都清楚的顯示爲一個小方塊。

 

當咱們縮小紋理時,由於沒有足夠的片斷用來繪製全部的紋理單元,許多細節將會丟失。




 

雙線性過濾


 

雙線性過濾使用雙線性插值平滑像素之間的過渡,而不是爲每一個片斷使用最近的紋理元素,OpenGL會使用四個鄰接的紋理元素,並在它們之間用一個線性插值算法作插值,這個算法與前面所講的平滑坐在着色同樣。咱們之因此稱它爲雙線性插值,是由於它是沿着兩個維度插值的。下面是使用雙線性差值放大後的圖像,它採用的紋理與前面的相同。






這個紋理如今看起來比之前平滑多了。但仍是有些鋸齒顯現出來,由於咱們把這個紋理擴展得太多,可是鋸齒不像使用最近鄰過濾那麼明顯。

 


MIP貼圖



儘管雙線性過濾很適合處理放大,可是對於縮小到超過必定的大小時,它就很差用了。一個紋理在渲染表面所佔大小減小得越多,就會有越多的紋理元素擁擠到每個片斷上。由於OpenGL的雙線性過濾只給每一個片斷使用四個紋理元素,咱們將會丟失不少細節。由於每一幀都要選擇不一樣的紋理元素,這還會引發噪音以及移動中的物體閃爍。

 

爲了克服這些缺陷,可使用MIP貼圖技術,它能夠用來生成一組優化過的不一樣大小的紋理。當生成這組紋理的時候,OpenGL會使用全部的紋理元素生成每一個級別的紋理,當過濾紋理時,還要確保全部的紋理元素都能被使用。在渲染時,OpenGL會根據每一個片斷的紋理元素數量爲每一個片斷選擇最合適的級別。

 

下圖是一組MIP貼圖的紋理,把它們合併在一當個圖上是爲了方便對比。



 圖2 MIP貼圖的紋理



使用MIP貼圖,會佔用更多的內存,可是渲染也會更快,這是由於較小級別的紋理在GPU的紋理緩存中佔用較少的空間。

 

爲了更好地理解MIP貼圖是如何提升縮小狀況下的質量,咱們比較一下那個可愛的機器人,使用雙線性過濾把紋理元素尺寸縮小到其原來的12.5%,以下圖:



 圖3 使用雙線性過濾縮小



就這種質量,可能還不如最近鄰過濾。看一下當咱們加入MIP貼圖時會獲得什麼。以下圖:



 圖4 使用MIP貼圖縮小



隨着MIP貼圖的使用,OpenGL將選擇最合適的紋理級別,而後用優化過的紋理作雙線性插值。每一個級別的紋理都是用來自全部紋理元素的信息構建的,所以獲得的圖形看起來更好些,保留了更多的細節。

 

三線性過濾

 

若是OpenGL在不一樣的MIP貼圖級別之間來回切換,當咱們用雙線性插值來使用MIP貼圖時,在其渲染的場景中,在不一樣級別的MIP貼圖切換時,咱們有時候能看到明顯的跳躍或者線條。咱們能夠切換到三線性插值,這樣,每一個片斷總共要使用8個紋理元素插值。這有助於消除每一個MIP貼圖級別之間的過渡,而且獲得一個更平滑的圖像。

 


3.程序中紋理參數表



方法GLES20.glTextParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_FILTER,「紋理過濾模式」);第二個參數指放大的狀況。

方法GLES20.glTextParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,「紋理過濾模式」);第二個參數指縮小的狀況。

第一個參數是告訴OpenGL這應該被做爲一個二維紋理對待。


表1  OpenGL紋理過濾模式

GL_NEAREST

最近鄰過濾

                        GL_NEAREST_MIPMAP_NEAREST

                    使用MIP貼圖的最近鄰過濾

        GL_NEAREST_MIPMAP_LINEAR

      使用MIP貼圖級別之間插值的最近鄰過濾

                      GL_LINEAR

                                雙線性插值

 GL_LINEAR_MIPMAP_NEAREST

使用MIP貼圖的雙線性插值

 GL_LINEAR_MIPMAP_LINEAR

三線性插值(使用MIP貼圖級別之間插值的雙線性過濾)



表2  每種狀況容許的紋理過濾模式

縮小 GL_NEAREST
GL_NEAREST_MIPMAP_NEAREST
GL_NEAREST_MIPMAP_LINEAR
GL_LINEAR
GL_LINEAR_MIPMAP_NEAREST
GL_LINEAR_MIPMAP_LINEAR
放大 GL_NEAREST
GL_LINEAR


下一篇紋理的應用效果圖以下:


相關文章
相關標籤/搜索