OPenGL紋理的載入

1. 位圖

像素數據由位圖(一系列表示像素值開啟和關閉0,1)來表示的。每個內存中存儲的位圖數據和像素開啟和關閉是一一對應的。

2. 像素包裝

像素數據的字節以特定方式與地址對齊的方式。比如說很多計算機CPU每四個字節從緩沖區讀取數據,而以每四個字節與地址對齊的方式,可以提高其讀寫效率。

3. 像素圖

像素圖屬于位圖,像素圖的位數比較多,一般為8位,16位和32位,可以顯示的顏色為2的位數次方,此外像素圖還有一個附加位,用來表示屏幕的兩度或者顏色值的強度。OpenGL中無法將像素數據寫入到顏色緩沖區,但是可以指定顏色緩沖區內容,也就是我們用一種形式表示圖像數據,通過直接讀取顏色緩沖區的數據而間接的提取出相關的像素數據。比如說可以通過這個函數進行提取。

void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);

x, y為矩形窗口在窗口左下角坐標,width和height為矩形寬和高,矩形為對應圖像數據的區域。pixels指針為圖像數據在內存中的地址。format為pixels指向的顏色緩沖區存取數據元素的顏色布局。type為pixels指向顏色緩沖區存取的數據類型。
需要注意的,glReadPixelds從圖形硬件中復制數據,通常通過總線傳輸到內存,這種情況下應用程序會被阻塞,直到內存傳輸完成,而且指定一個與本地圖形硬件不同的像素布局,也會帶來額外的開銷.

4. 包裝的像素格式

如果一個字節等于8位,通常我們用八位表示三原色的一個分量,那么顯示一種顏色需要三個字節,但是經過包裝后,比如說我們可以用八位就可以表示一種顏色,比如說從高位到低位,沒三位表示三原色的一種分量,后一位表示一種三原色的分量,這樣對圖像數據進行包裝,可以節省大量的內存的空間.或者更快的進行操作.

5. 載入紋理

將紋理數據載入到內存中,在OpenGL一般我們通過下面三個函數

void glTexImage1d(GLenum target, GLint level, GLint internalformat , GLseizei width, GLint border , GLenum format, GLenum type, void *data)
void glTexImage2d(GLenum target, GLint level, GLint internalformat , GLseizei width, GLseizei height, GLint border , GLenum format, GLenum type, void *data)
void glTexImage3d(GLenum target, GLint level, GLint internalformat , GLseizei width, GLseizei height,  GLseizei depth, GLint border , GLenum format, GLenum type, void *data)

target參數為載入紋理單元的模式,level為mip的層次,internalformat為每個紋理單元存儲的顏色成分,如果指定顏色組成的特定方式,也可作為壓縮紋理數據的參數,width,height,depth指定了被加載紋理數據的范圍, border為每個紋理單元額外的邊界。format為紋理數據的顏色布局,type為存儲到內存中的紋理數據類型,data為紋理數據對應的地址指針。

6.從顏色顏色緩存區讀取紋理數據

可以使用下面兩個函數

void glCopyTexImage1d(GLenum target, GLint level, GLint internalformat , GLint x, GLseizei width, GLint border)
void glCopyTexImage2d(GLenum target, GLint level, GLint internalformat , GLint x, GLint y, GLseizei width, GLseizei height, GLint border)

其中x,y為指定內存中要加載紋理的位置,需要注意的是顏色緩沖區沒有深度的概念,故不能加載三維的紋理數據。

7. 更新紋理

頻繁的載入紋理數據,實際上是對內存的寫操作,內存的寫操作是很耗性能的,當我們不在需要這段紋理時,這時候我們可以在這段紋理的內存上進行紋理的替換或者部分替換,而避免再次重新寫入新的紋理數據。下面幾個函數可以完成紋理更新

void glTexSubImage1d(GLenum target, GLint level, GLint xOffset, GLseizei width, GLint border , GLenum format, GLenum type, void *data )
void glTexSubImage2d(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLseizei width, GLseizei height, GLint border , GLenum format, GLenum type, void *data)
oid glTexSubImage3d(GLenum target, GLint level , GLint xOffset, GLint yOffset, GLint zOffset, GLseizei width, GLseizei height, GLint border , GLenum format, GLenum type, void *data)

其中xOffset,yOffset,zOffset,為需要更新的紋理在原紋理的坐標偏移量。

8.在顏色顏色緩存區更新紋理

void glCopyTexSubImage1d(GLenum target, GLint level, GLint xOffset, GLint x, GLint y,   GLseizei width )
void glCopyTexSubImage2d(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint x, GLint y,  GLseizei width, GLseizei height)
oid glCopyTexSubImage3d(GLenum target, GLint level , GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y, GLseizei width, GLseizei height)

需要注意的地方從顏色緩存區讀取紋理數據是沒有glCopyTexImage3d函數的,這是因為顏色緩沖區是沒有深度概念的,只可以將2D彩色圖片設置成2D紋理,但是我們更新顏色緩沖區的紋理是可以使用glCopyTexSubImage3d函數的,因為紋理有深度的概念,我們可以用紋理單元平面來設置一個二維的紋理。

9.紋理對象

當載入紋理數據后,這時候我們是需要管理這些紋理的,如果用到哪個紋理狀態就加載哪個紋理數據或者更新哪個紋理的話,這樣顯然是很耗費性能的,紋理對象允許一次加載多個紋理,通過一段特定的無符號整形數據一個指針指向這段紋理內存,這樣我們通過紋理對象可以方便的進行多個紋理的管理。
首先使用下面這個函數進行紋理對象的分配

void glGenTextures(GLSizei n, GLint * textures)

n為紋理對象的個數, textures為紋理對象集合的指針
通過下面的函數進行紋理與紋理對象的綁定

void glBindTexture(GLEnum target, GLint *texture)

target為紋理數據的坐標形式,teture為指向紋理內存的指針。
可以使用下面的函數進行紋理對象的刪除

void glDeleteTextures(GLSizei n, GLint * textures)

n為要刪除的紋理個數,textures為要刪除的紋理集合
可以使用下面的函數判斷紋理對象是否有綁定紋理狀態

GLboolean GLIsTexture(GLint teure)

teure為要判讀是否存在的紋理對象

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容