載入紋理與使用glGenTextures時應注意的一點(解決吃記憶體)[轉]
glGenTextures
glGenTextures(GLsizei n, GLuint *textures)函數說明
n:用來產生紋理的數量
textures:儲存紋理索引的
glGenTextures函數根據紋理參數返回n個紋理索引。紋理名稱集合不必是一個連續的整數集合。
(glGenTextures就是用來產生你要操作的紋理對象的索引的,比如你告訴OpenGL,我需要5個紋理對象,它會從沒有用到的整數裡返回5個給你)
glBindTexture實際上是改變了OpenGL的這個狀態,它告訴OpenGL下面對紋理的任何操作都是對它所綁定的紋理對象的,比如glBindTexture(GL_TEXTURE_2D,1)告訴OpenGL下面代碼中對2D紋理的任何設定都是針對索引為1的紋理的。
產生紋理函數假定目標紋理的面積是由glBindTexture函數限制的。先前調用glGenTextures產生的紋理索引集不會由後面調用的glGenTextures得到,除非他們首先被glDeleteTextures刪除。你不可以在顯示列表中包含glGenTextures。
void glGenTextures(GLsizei n, GLuint *texture);
該函數用來產生紋理名稱。這裡紋理名稱GLuint *texture是整型的,因此也可以理解為這個函數為這n個紋理指定了n個不同的ID。
在用GL渲染的時候,紋理是很常見的東西。使用紋理之前,必須執行這句命令為你的texture分配一個ID,然後綁定這個紋理,載入紋理映像,這之後,這個紋理才可以使用。載入紋理的代碼如下:
BOOL LoadTextures(IplImage *pImage, GLuint *pTexture)
{
int Status=FALSE;
if(pImage != NULL)
{
Status=TRUE;
glGenTextures(1, &pTexture[0]); //注意這裡
glBindTexture(GL_TEXTURE_2D, pTexture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3,
pImage->width, pImage->height,
0, GL_BGR, GL_UNSIGNED_BYTE, (unsigned char *)pImage->imageData);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
return Status;
}
使用上面這個函數時需要小心,這個函數只能放在迴圈外面使用!如果你想在迴圈中重複利用這個texture[0],給它載入不同的紋理(比如,你想在視窗中顯示順序圖表像),而把這個函數放在迴圈內部調用的話,那麼當程式迴圈足夠多次之後,你的電腦將變得巨慢無比,甚至導致死機。原因就是反覆地調用glGenTextures(1, &pTexture[0])。這個問題產生的機制我並不清楚,但是我今天實實在在的遇到了。
所以,上面這個函數一般都是放在迴圈外面,視窗初始化的時候,用於給背景載入紋理。那麼,如果我必須要在迴圈中渲染序列幀的話,該怎麼做呢?我們可以對上面的函數加一點小小的改變,如下:
BOOL LoadTextures(IplImage *pImage, GLuint texture)
{
int Status=FALSE;
if(pImage != NULL)
{
Status=TRUE;
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, 3,
pImage->width, pImage->height,
0, GL_BGR, GL_UNSIGNED_BYTE, (unsigned char *)pImage->imageData);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
return Status;
}
在視窗初始化的時候先執行一遍:
glGenTextures(1, &texture[0]);
然後在你的迴圈內部調用:
IplImage *videoFrame = cvQueryFrame(capture);
LoadTextures(videoFrame, texture[0]);
這樣就可以顯示映像幀了,也不會再出現電腦運行速度變慢的問題了。總之,千萬不要給一個texture重複分配ID。
我自己寫的這個LoadTextures函數提供了映像buffer的介面,可以從外面讀取視訊框架並傳給這個函數,綁定紋理, 使用起來比較靈活。
分類:
OpenGL ES