文章說明
本文是學習OpenGL的筆記,主要參考大神JoeyDeVries
的LearnOpenGL第六課《紋理》,并將教程中的代碼基于Qt進行實現。
學習目標
- 掌握紋理基本知識
- 掌握紋理貼圖
目錄結構
|-
|-- HelloTextures|--- hello_textures.cpp|--- hello_textures.h|--- main.cpp|--- CMakeLists.txt
|-- CMakeLists.txt
整個項目的全部CMakeLists.txt文件與上一篇 Qt中的OpenGL (3)[著色器] 中的內容基本一致,只需要將全部HelloShader替換成HelloTextures就可以了。
在前邊的教程中繪制三角形的時候用到頂點的位置和顏色兩個屬性,三個頂點屬性數據可以完成一個純色(三點顏色一致)或者彩色(三點顏色不一致)的三角形,但下面這種顏色的三角形應該就不會只有三個頂點屬性這么簡單了。
要繪制上面這個三角形就需要用到大量的頂點屬性,并且每個頂點屬性都需要帶有顏色屬性,并且顏色屬性的設置要細致到每個像素,這種做法會增加額外的開銷。這個時候就需要用到紋理了,簡單來說紋理就是將圖片按照規則貼到物體模型上。
紋理坐標
在現實生活中如果需要給一個物體貼上圖片正常情況下是要先測量物體大小然后準備一個合適的貼紙,最后物體的邊角對應貼紙的邊角完全貼合,在開發過程中模型與紋理圖片之間經常存在不匹配的情況,如下圖所示:
上圖中紋理圖片的像素是200 * 200而三角形在屏幕上顯示的像素是1000 * 1000這無論如何也無法一一對應了。此時,就需要使用紋理坐標(UV),一般使用U和V表示紋理坐標,其中U表示橫坐標百分比而V表示縱坐標百分比,使用百分比的方式代替實際數值的對應方式,紋理坐標起始于左下角(0, 0),終止于右上角(1, 1)。
類似于上面紋理圖映射到圖形的場景,紋理設置如下:
- 三角形左下角對應紋理圖左下角因此紋理坐標就是(0.0, 0.0),對應的像素值就是w=0, h=0
- 三角形右下角對應紋理圖右下角因此紋理坐標就是(1.0, 0.0),對應的像素值就是w=200, h=0
- 三角形頂角對應紋理圖的上中點因此紋理坐標就是(0.5, 1.0),對應的像素值就是w=100, h=200
注意:除了設置的紋理坐標外,其他紋理坐標都是根據已設置的紋理坐標經過插值計算而來的。
紋理過濾
單獨使用紋理坐標也不能解決需要繪制的像素和實際紋理圖片像素不匹配問題,解決繪制像素與紋理像素不匹配問題有兩種方式,分別是Nearest Neighbor Filtering和Linear Filtering。
鄰近過濾(Nearest Neighbor Filtering)
這是一種默認的過濾方式,根據UV坐標計算出來的小數坐標,取最近的整數坐標像素,這種取值方式可能回去到會多次相同的像素色塊,導致顆粒感比較強是一種像素風格。
線性插值過濾(Linear Filtering)
另外一種是根據UV計算出來的小數坐標,綜合周邊像素得到新的像素。這種方式根據周圍像素產生新的像素色塊,相當于對原始紋理圖片進行擴充。
這兩種過濾方式在解決像素不匹配問題上并沒有絕對的使用規則。一般情況使用情況如下:
- 需要繪制像素超過圖片紋理像素,使用線性過濾。
- 需要繪制像素少于圖片紋理像素,使用鄰近過濾。
設置過濾方式的函數如下,這個函數包含了紋理的過濾方式設置和紋理的環繞方式,這里先說過濾方式相關參數
void glTexParameteri(GLenum target, GLenum pname, GLint param);
-
設置紋理過濾方式
- target: 指定紋理目標類型,它表示要設置參數的紋理類型。
- pname: 指定要設置的紋理參數名稱。
- param: 指定過濾方式。
-
target可設置參數,不區分過濾設置和環繞設置
-
GL_TEXTURE_1D
:一維紋理,常用于模擬漸變效果,如顏色漸變條。 -
GL_TEXTURE_2D
:二維紋理,最常用的紋理類型,用于給物體表面貼圖,像給立方體的每個面貼上不同的圖片。 -
GL_TEXTURE_3D
:三維紋理,包含深度信息,可用于表示體積數據,例如醫學上的 CT 掃描數據。 -
GL_TEXTURE_CUBE_MAP
:立方體貼圖,由 6 個二維紋理組成,用于模擬環境反射,比如天空盒效果。 -
GL_TEXTURE_1D_ARRAY
:一維紋理數組,由多個一維紋理組成,可用于存儲多個相關的一維紋理數據。 -
GL_TEXTURE_2D_
-