OpenGL紋理詳解(上)

2021-07-28 18:30:21 字數 3099 閱讀 3781

現實生活中,紋理最通常的作用是裝飾我們的物體模型,它就像是貼紙一樣貼在物體表面,使得物體表面擁有圖案。但實際上在opengl中,紋理的作用不僅限於此,它可以用來儲存大量的資料,乙個典型的例子就是利用紋理儲存地形資訊。

現代opengl中,紋理物件和頂點陣列物件(vao)及快取物件(vbo)一樣,需要呼叫glgentextures函式生成。

生成紋理物件

同樣的,紋理物件需要進行繫結。opengl中紋理可以分為1d,2d和3d紋理,我們在繫結紋理物件的時候需要指定紋理的種類。由於本文將以一張為例,因此我們為我們的紋理物件繫結乙個gl_texture_2d的紋理。

2d紋理繫結

在opengl中,我們通常將紋理中的畫素將按照紋理座標進行編址,紋理座標系是乙個空間直角座標系,橫軸為s軸,縱軸為t軸,垂直於螢幕的座標軸為r軸。在我們的2d紋理中,由於沒有r軸,我們也可以將橫軸稱為u 縱軸稱為v軸,也就是我們所說的uv座標系。但和opengl座標系所不同的是:紋理座標系的(0,0)點位於紋理的左下角,而(1,1)點位於紋理的右上角。

2d紋理座標系

取樣通過紋理座標獲取畫素顏色資訊的過程稱為取樣,而取樣的結果會根據紋理引數設定的不同而千差萬別。opengl中設定紋理引數的api介面為gltextureparameter,我們所有的紋理引數都由這個介面設定,下面我們介紹幾種常用的紋理引數的配置。

紋理座標的範圍與opengl的螢幕座標範圍一樣,是0-1。超出這一範圍的座標將被opengl根據gl_texture_wrap引數的值進行處理:

gl_repeat: 超出紋理範圍的座標整數部分被忽略,形成重複效果。

gl_mirrored_repeat: 超出紋理範圍的座標整數部分被忽略,但當整數部分為奇數時進行取反,形成映象效果。

gl_clamp_to_edge:超出紋理範圍的座標被擷取成0和1,形成紋理邊緣延伸的效果。

gl_clamp_to_border: 超出紋理範圍的部分被設定為邊緣色。

這四種模式所產生的紋理效果如下:

紋理邊界顏色的設定

這兩行**執行後,紋理的邊界顏色將被設定為紅色。

過濾由於紋理座標和我們當前的螢幕解析度是無關的,所以當我們為乙個模型貼紋理時,往往會遇到紋理尺寸與模型尺寸不符的情況,這時,紋理會因為縮放而失真。處理這一失真的過程我們稱為過濾,在opengl中我們有如下幾種常用的過濾手段:

gl_nearest: 最臨近過濾,獲得最靠近紋理座標點的畫素。

gl_linear: 線性插值過濾,獲取座標點附近4個畫素的加權平均值。

gl_nearest_mipmap_nearest:用於mipmap,下節將詳細介紹。

gl_linear_mipmap_nearest:

gl_nearest_mipmap_linear:

gl_linear_mipmap_linear:

在我們討論mipmap之前,我們來看看前兩種過濾演算法在紋理影象面前會產生怎樣的過濾效果(原始大小和模型大小相差16倍):

兩種插值過濾演算法過濾效果

從這裡我們可以看出,線性插值演算法的過濾效果似乎更加平滑,但並不表示這種演算法適合所有的場合,如果我們需要對影象進行馬賽克處理或模擬乙個8位遊戲機的遊戲畫面時,最臨近過濾演算法是最好的選擇。

我們可以單獨為紋理縮放指定不同的過濾演算法,這兩種情況下紋理引數設定分別對應為:gl_texture_min_filter和gl_texture_mag_filter.

分別為紋理縮放指定線性過濾演算法 

mipmaps

正如前面所提到的,還有一種過濾紋理的方法---mipmaps。如下圖所示: mipmaps 將紋理按照1/2的比例縮小並生成副本,以此類推直到紋理只有1x1大小(這裡是紋理座標,不是真實畫素大小)。取樣時我們根據當前縮小比率來選擇合適大小的紋理,按照線性過濾或最鄰近過濾來取樣。比如,我們要用做貼圖的紋理大小為 64x32,對它做下取樣生成32x16,16x8,8x4,4x2,2x1,1x1的紋理,如果要渲染的區域大小為14x6,那麼我們要麼選16x8的紋理,要麼選16x8與8x4的兩塊紋理做加權平均。

mipmaps例項

mipmaps是乙個功能強大的紋理技術,它可以提高渲染的效能以及提公升場景的視覺質量。它可以用來解決使用一般的紋理貼圖會出現的兩個常見的問題:

1.  閃爍,當螢幕上被渲染區域與它所應用的紋理影象相比顯得非常小時,就會出現閃爍。尤其當視口和物體在移動的時候,這種負面效果更容易被看到。

2. 效能問題。如果我們的貼紋理的區域離我們非常遠,遠到在螢幕中只有乙個畫素那麼大小時,紋理的所有紋素都集中在這一畫素中。這時,我們無論做鄰近過濾還是做線性過濾時都不得不將紋理的所有紋素計算在內,這種計算效率將大大影響我們的取樣效率,而紋理的資料量越大,對效率的影響就會更大。

使用mipmaps技術就可以解決上面那兩個問題。當載入紋理的同時預處理生成一系列從大到小的紋理,使用時只需選擇合適大小的紋理載入就行了。這樣雖然會增加一些額外的記憶體(乙個正方形紋理將額外占用約30%的記憶體),但將大大提高了我們的取樣效率和取樣質量。

生成mipmaps的過程很簡單,只需要在載入紋理後執行下面一行**:

生成mipmaps

使用mipmaps也很簡單,只需設定過濾引數為以下4種中的任意一種:

gl_nearest_mipmap_nearest:選擇最鄰近的mip層,並使用最鄰近過濾。

gl_nearest_mipmap_linear:對兩個mip層使用最鄰近過濾後的取樣結果進行加權平均。

gl_linear_mipmap_nearest:選擇最鄰近的mip層,使用線性插值演算法進行過濾。

gl_linear_mipmap_linear:對兩個mip層使用線性插值過濾後的取樣結果進行加權平均,又稱三線性mipmap。

在選擇這幾種過濾方法時,我們需要考慮的是效率和質量,線性過濾往往更加平滑,但隨之而來的是更多的取樣次數;而臨近過濾減少了取樣次數,但最終視覺效果會比較差。

OpenGL載入紋理深入詳解。

opengl進行紋理對映的基本流程 1,首先要開啟紋理對映的功能。glenable gl texture 2d 2,載入位圖資源。3,將位圖資源轉化成紋理。4,釋放位圖資源。5,使用紋理,繪圖。閒話不多說,直接上 這裡插一句,在opengl裡面,申明乙個紋理 位圖轉化成紋理 需要三個步驟 1,首先我...

opengl紋理單元

可以這樣簡單的理解為 顯示卡中有n個紋理單元 具體數目依賴你的顯示卡能力 每個紋理單元 gl texture0 gl texture1等 都有gl texture 1d gl texture 2d等,如下 cpp view plain copy print struct textureunit te...

openGL 紋理使用

最近找了點資料學習了下opengl 紋理的使用 先有個 整體把握,然後再去看大部頭中的細節講解,感覺這樣的學習方式好些 總結下紋理使用總體流程 1 啟用紋理 glenable gl texture 2d 2 載入紋理 3 紋理 的顯示 載入紋理 1 讀取紋理影象高寬和畫素資料到記憶體中,老版本 op...