1. 程式人生 > >OpenGL ES 理解紋理與紋理過濾

OpenGL ES 理解紋理與紋理過濾

1.理解紋理

OpenGL中的紋理可以用來表示影象,照片,甚至由一個數學演算法生成的分形資料。每個二維的紋理都由許多小的紋理元素組成,它們是小塊的資料,類似於我們前面討論過的片段和畫素。要使用紋理,最常用的方式是直接從一個影象檔案載入資料。

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

\

圖1 OpenGL二維紋理座標

對一個OpenGL紋理來說,它沒有內在的方向性,因此我們可以使用不同的座標把它定向到任何我們喜歡的方向上。然而,大多數計算機影象都有一個預設的方向,它們通常被規定為Y軸向下,Y的值隨著向影象的底部移動而增加。只要我們記住,如果想用正確的方向觀察影象,那紋理座標就必須要考慮這點,這就不會給我們帶來任何麻煩。

在標準OpenGL ES 2.0中,紋理不必是正方形,但是每個維度都應該是2的冪(POT)。這就意味著每個維度都是這樣的一個數字,如128,256,512等。這樣規定的原因在於非POT紋理可以被使用的場合非常有限,而POT紋理使用於各種情況。

紋理的尺寸也有一個最大值,它根據不同的實現而變化,但是通常都比較大,比如2048*2048。

2.理解紋理過濾

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

首先,講述兩個基本的過濾模式:最近鄰過濾和雙線性插值。還有其他的過濾模式,以後的博文會講解。我們會使用下面的影象闡述每一種過濾模式。

\

最近鄰過濾

這個方式為每個片段選擇最近的紋理元素。當我們放大紋理時,它的鋸齒效果看起來相當明顯,如下圖所示。

\

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

當我們縮小紋理時,因為沒有足夠的片段用來繪製所有的紋理單元,許多細節將會丟失。

\

雙線性過濾

雙線性過濾使用雙線性插值平滑畫素之間的過渡,而不是為每個片段使用最近的紋理元素,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

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

\

相關推薦

opengl es 渲染方式 紋理座標設定 ,OpenGL ES 模型檢視之縮放操作

OpenGl ES關於渲染方式有以下兩種: RENDERMODE_CONTINUOUSLY和RENDERMODE_WHEN_DIRTY。 預設渲染方式為RENDERMODE_CONTINUOUSLY,這兩種渲染的含義是: RENDERMODE_CONTINUOUSL

OpenGL ES 理解紋理紋理過濾

1.理解紋理 OpenGL中的紋理可以用來表示影象,照片,甚至由一個數學演算法生成的分形資料。每個二維的紋理都由許多小的紋理元素組成,它們是小塊的資料,類似於我們前面討論過的片段和畫素。要使用紋理,最常用的方式是直接從一個影象檔案載入資料。 每個二維紋理都有其自己

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

1.理解紋理 OpenGL中的紋理可以用來表示影象,照片,甚至由一個數學演算法生成的分形資料。每個二維的紋理都由許多小的紋理元素組成,它們是小塊的資料,類似於我們前面討論過的片段和畫素。要使用紋理,最常用的方式是直接從一個影象檔案載入資料。 每個二維紋理都有其自己的座標

Opengl ES 1.x NDK實例開發之六:紋理貼圖

otto absolute decode super rep mit his viewport 一個 開發框架介紹請參見:Opengl ES NDK實例開發之中的一個:搭建開發框架 本章在第三章(Opengl ES 1.x NDK實例開發之三:多邊形的旋轉)的基礎

OpenGL ES 紋理設定

紋理過濾 紋理取樣 最近點取樣 線性紋理取樣 MIPMAP紋理 紋理過濾 紋理拉伸:重複拉伸和擷取拉伸 用於指定紋理座標超過(00.0,1

android平臺下OpenGL ES 3.0實現2D紋理貼圖顯示bitmap

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

OpenGL ES 紋理壓縮之ETC (二)

前面介紹了OpenGL ES2.0 支援的壓縮ETC1;下面我們來學習一下ETC2。 從opengl es3.0 開始支援ETC2紋理壓縮,而這種壓縮可以支援透明通道。 下面看如何使用 載入pkm檔案 public static byte[] loadDataFromAsse

OpenGL ES (3):平面圖形-表面紋理貼圖

1.簡介 上一篇已經將一個平面圖形繪製出來了,這一次我們將在上一次繪製出來的圖形的表面上進行紋理貼圖。 圖片準備:(寬高須為2的N次方) 最終圖片是以Bitmap形式。現在考慮如何把這張圖片對映到繪製的平面上? 所以這裡也需要一個數組float[] 用於設定紋理座

OpenGL ES (16): 紋理貼圖

1.前言 圖片如下:紋理座標為 左上角為(0,0),右下角為(1,1) 我們繪製一個正方形,頂點座標資料如下: 此次程式碼不包含z軸,預設為0。 要做的事就是把圖片貼到正方形的表面,並繪製出正方形。 所以上面的紋理座標和頂點座標的順序要一致。這樣繪製的圖片才

初學Android,OpenGL ES之使用紋理(八十三)

在網上發現這些講紋理的文章,非常不錯android 遊戲導引(4. 簡單紋理貼圖)Android OpenGL es 紋理座標設定與貼圖規則Android OpenGL | ES給立方體進行紋理對映這篇的例子也是立方體的紋理,不過是用手指劃過讓立方體旋轉使用紋理的重要程式碼如

從零開始OpenGL ES(四) 繪製紋理 圖片

理論 首先是兩個座標系 假如現在有一張圖片,是通過紋理座標系繪製出來的,圖片的左上角(0,0),左下角(0,1), 那麼我需要把紋理座標系和頂點座標系對齊, 那麼要把紋理座標系中(0,0)這個點,放到頂點座標系中的(-1,0)這個點. 相應的要把紋理座標系的

android opengl es--紋理對映,光照

import zhou.ne.he.four.FourRend; import zhou.ne.he.one.OneRend; import zhou.ne.he.thri.ThriRend; import zhou.ne.he.two.TwoRend; import a

Android OpenGL ES 2.0繪圖:繪製紋理

紋理,在OpenGL中,可以理解為載入到顯示卡視訊記憶體中的圖片。 Android裝置在 2.2開始支援OpenGL ES2.0,從前都是ES1.0 和 ES1.1的版本。 簡單來說,OpenGL ES是為了嵌入裝置進行功能剪裁後的OpenGL版本。ES2.0是和1.x版本不相容的,區別和相容性參見

OpenGL學習十九:紋理過濾

當物體放大縮小時導致投影在上面的紋理也隨著變化,OpenGL為了 優化其細節使其效果更好,因此可以採用紋理過濾 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GL_TEXTURE_MA

Android OpenGL ES正方體紋理貼圖(每個面一張)

正方體的紋理貼圖步驟如下: 1.陣列 1.1:頂點陣列 1.2:三角形 1.3:貼圖陣列 2.onSurfaceChanged:與3D的一樣 3.onSurfaceCreated:需要新增東西 3.1允許2D貼圖gl.glEnable(GL10.GL_TEXTURE_2D

初學Android OpenGL ES之使用紋理 八十三

mod frame ava als content detect www 大小 net 在網上發現這些講紋理的文章,非常不錯 android 遊戲導引(4. 簡單紋理貼圖) http://www.cnblogs.com/shengdoushi/archive/2011/0

Android使用OpenGL ES顯示紋理(使用NDK開發)

書上第四章最後開始介紹使用OpenGL來顯示一個2D紋理,其實做音視訊2D基本滿足絕大多數要求了,下面簡單分析一下原始碼中的流程。 EGL環境初始化 首先我們需要在Java環境中初始化一個SurfaceView,然後在回撥中我們傳入surface。這裡我

android opengl es新增紋理,繪製立方體紋理,立方體使用不同紋理

           紋理就是給物體表面新增圖片,色彩之類,可以認為是上色。            基本步驟: 開啟紋理開關建立紋理繫結紋理設定紋理引數生成紋理設定紋理頂點資料 具體看如下程式碼: @Override public void onSurfaceCrea

OpenGL ES 紋理貼圖

頂點座標和紋理座標 在沒有投影矩陣的情況下,我們要傳給頂點著色器的座標值都在(-1,1)範圍內,超出了這個範圍將不可見。因此對於一個四邊形的繪製,我們經常看到下面的頂點座標: GLfloat vertices[] = { // P

Android OpenGL ES 2.0繪圖:繪製紋理

http://mobile.51cto.com/aengine-437172.htm publicclass MyGLSurfaceView extends GLSurfaceView { public MyGLSurfaceView(Context context