日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】OpenGL超级宝典笔记——纹理映射Mipmap

發(fā)布時間:2023/12/9 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】OpenGL超级宝典笔记——纹理映射Mipmap 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址?http://my.oschina.net/sweetdark/blog/177812?, 感謝作者,若非法轉(zhuǎn)載請聯(lián)系本人。

目錄[-]

  • Mipmapping
  • Mipmap過濾
  • 構(gòu)建Mip層
  • Mipmaps 硬件生成
  • LOD(多細節(jié)層次)偏好
  • 紋理對象
  • 管理多個紋理
  • 常駐紋理
  • 紋理優(yōu)先級
  • 回顧

Mipmapping

Mipmap是一個功能強大的紋理技術(shù),它可以提高渲染的性能以及提升場景的視覺質(zhì)量。它可以用來解決使用一般的紋理貼圖會出現(xiàn)的兩個常見的問題:

  • 閃爍,當(dāng)屏幕上被渲染物體的表面與它所應(yīng)用的紋理圖像相比顯得非常小時,就會出現(xiàn)閃爍。尤其當(dāng)相機和物體在移動的時候,這種負面效果更容易被看到。
  • 性能問題。加載了大量的紋理數(shù)據(jù)之后,還要對其進行過濾處理(縮小),在屏幕上顯示的只是一小部分。紋理越大,所造成的性能影響就越大。

Mipmap就可以解決上面那兩個問題。當(dāng)加載紋理的時候,不單單是加載一個紋理,而是加載一系列從大到小的紋理當(dāng)mipmapped紋理狀態(tài)中。然后OpenGl會根據(jù)給定的幾何圖像的大小選擇最合適的紋理。Mipmap是把紋理按照2的倍數(shù)進行縮放,直到圖像為1x1的大小,然后把這些圖都存儲起來,當(dāng)要使用的就選擇一個合適的圖像。這會增加一些額外的內(nèi)存。在正方形的紋理貼圖中使用mipmap技術(shù),大概要比原先多出三分之一的內(nèi)存空間。

mipmap有多少個層級是有g(shù)lTexImage的第二個參數(shù)level決定的。層級從0開始,0,1,2,3這樣遞增。如果沒有使用mipmap技術(shù),只有第0層的紋理會被加載。在默認情況下,為了使用mipmap,所有層級都會被加載。但我們可以通過紋理參數(shù)來控制要加載的層級范圍,使用glTexParameteri, 第二個參數(shù)為GL_TEXTURE_BASE_LEVEL來指定最低層級的level,第二個參數(shù)為GL_TEXTURE_MAX_LEVEL指定最高層級的level。例如我只需要加載0到4層級的紋理:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);

除此之外,我們還可通過GL_TEXTURE_MIN_LOD和GL_TEXTURE_MAX_LOD來限制紋理的使用范圍(最底層和最高層)。

Mipmap過濾

Mipmap的紋理過濾模式如下表:

常量描述
GL_NEAREST在mip基層上使用最鄰近過濾
GL_LINEAR在mip基層上使用線性過濾
GL_NEAREST_MIPMAP_NEAREST選擇最鄰近的mip層,并使用最鄰近過濾
GL_NEAREST_MIPMAP_LINEAR在mip層之間使用線性插值和最鄰近過濾
GL_LINEAR_MIPMAP_NEAREST選擇最鄰近的mip層,使用線性過濾
GL_LINEAR_MIPMAP_LINEAR在mip層之間使用線性插值和使用線性過濾,又稱三線性mipmap

如果紋理過濾選擇為GL_NEAREST或GL_LINEAR模式,那么只有基層的紋理會被加載,其他的紋理將會被忽略。我們必須指定其中一個mipmap過濾器,這樣才能使用所有已加載的紋理。這個mipmap過濾器的常量是GL_FILTER_MIPMAP_SELECTOR的形式。其中FLILTER指定了過濾模式,SELECTOR指定了如何選擇mipmap層。例如GL_NEAREST_MIPMAP_LINEAR模式,它的SELECTOR是GL_LINEAR,它會在兩個最鄰近的mip層中執(zhí)行線性插值,然后得出的結(jié)果又由被選擇的過濾器GL_NEAREST進行過濾。

其中GL_NEAREST_MIPMAP_NEAAREST具有很好的性能,也能夠解決閃爍的問題,但在視覺效果上會比較差。其中GL_LINEAR_MIPMAP_NEAREST常用于游戲加速,使用了質(zhì)量較高的線性過濾,和快速的選擇的方式(最鄰近方式)。

使用最鄰近的方式作為mipmap選擇器的效果依然不能令人滿意。從某一個角度去看,常常可以看到物體表面從一個mip層到另一個mip層的轉(zhuǎn)變。GL_LINEAR_MIPMAP_LINEAR和GL_NEAREST_MIPMAP_LINEAR過濾器在mip層之間執(zhí)行一些額外的線性插值,以消除不同層之間的變換痕跡,但也需要一些額外的性能開銷。GL_LINEAR_MIPMAP_LINEAR具有最高的精度。

構(gòu)建Mip層

mip貼圖需要加載更小的基本紋理圖像以便使用。但我們手頭上沒有這些更小的紋理圖像,怎么辦呢。GLU函數(shù)庫提供了一個很方便的方法gluBuildMipmaps,它會幫我們縮放圖像并通過類似glTexImage的函數(shù)加載圖像。支持1維、2維、3維的圖像,函數(shù)原型如下:

int gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLint width, GLenum format, GLenum type, const void *data);

int gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLint width, GLint height, GLenum format, GLenum type, const void *data);

int gluBuild3DMipmaps(GLenum target, GLint internalFormat, GLint width, GLint height, GLint depth, GLenum format, GLenum type, const void *data);

參數(shù)的意義與glTexImage相同。但沒有l(wèi)evel參數(shù)來指定mipmap的層級,也不支持紋理邊界。使用這個函數(shù)未必能夠獲得高質(zhì)量的較小的紋理貼圖,只是比較方便。要使用高質(zhì)量的不同比例的紋理貼圖,最好是自己手工制作,然后加載。GLU庫是使用box過濾器(簡單地就是對給定范圍的像素進行加權(quán)平均,例如7X7的box filter,你就需要對49個像素進行平均)

新版的GLU庫中可以使用gluBuild*MipmapLevels來更好的控制加載的紋理層級

int gluBuild1DMipmapLevels(GLenum target, GLint internalFormat, GLint width, GLenum format, GLenum type, GLint base, GLint max, const void *data);

int gluBuild2DMipmapLevels(GLenum target, GLint internalFormat, GLint width, GLint height, GLenum format, GLenum type, GLint base, GLint max, const void *data);

int gluBuild3DMipmapLevels(GLenum target, GLint internalFormat, GLint widht, GLint height, GLint depth, GLenum format, GLenum type, GLint base, GLint max, const void *data);

創(chuàng)建從base到max層的紋理數(shù)據(jù)。

Mipmaps 硬件生成

使用OpenGL的硬件加速來生成所需要的紋理。函數(shù)調(diào)用如下:

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

當(dāng)這個參數(shù)被設(shè)置為GL_TRUE時,所有調(diào)用glTexImage或者glTexSubImage都會自動更新紋理貼圖(第0級)和所有更低層的紋理。通過使用硬件加速會比使用glu庫中的gluBuildMipmap要快,但這個特性本來只是個擴展,在OpenGL1.4才被納入OpenGL核心API的。

LOD(多細節(jié)層次)偏好

當(dāng)mipmapping被啟用時,OpenGL會根據(jù)各個mip層的大小和幾何圖形在屏幕上的面積來決定哪一個mip層被選擇。OpenGL會選擇最合適的mip貼圖層與屏幕上的紋理表示形式進行匹配。我們可以告訴OpenGL向后(選擇更大的mip層)或向前(選擇更小的mipmap層)來調(diào)整選擇的標準。使用更小的mip層可以提高性能,選擇更大的mip層可以銳化紋理映射的對象。這個偏好設(shè)置示例如下:

glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, –1.5);

上面會使的細節(jié)紋理層傾向于使用更高層的細節(jié)(更小的level層參數(shù)),從而使得紋理的外觀更為銳利,代價是紋理處理的開銷大一些。

紋理對象

glTexImage, glTexSubImage和gluBuildMipmaps這些函數(shù)的調(diào)用消耗的時間特別多。這些函數(shù)大量的移動內(nèi)存,有時需要重新調(diào)整數(shù)據(jù)的格式來適應(yīng)一些內(nèi)部的表示。在紋理之間切換或者重新加載不同的紋理圖片會帶來較大的性能開銷。

為了減少這些開銷,我們可以使用紋理對象。紋理對象允許你一次性加載多個紋理狀態(tài)(包括紋理圖像),然后在它們之間快速切換。紋理狀態(tài)由當(dāng)前綁定的紋理對象來維護。紋理的名稱由unsigned int類型來標識。使用下面的函數(shù)來生成一定數(shù)量的紋理對象:

void glGenTextures(GLsizei n, GLuint *textures);

上面的函數(shù)調(diào)用指定了紋理對象的數(shù)量,和存儲紋理對象名稱的數(shù)組。我們可以通過紋理對象名稱來操作紋理狀態(tài)。綁定其中的一個紋理狀態(tài)的函數(shù)調(diào)用如下:

void glBindTexture(GLenum target, GLuint texture);

target參數(shù)必須是GL_TEXTURE_1D,GL_TEXTURE_2D或者GL_TEXTURE_3D.texture是紋理名稱指定要綁定的紋理對象。在此函數(shù)之后,紋理圖像的加載和紋理參數(shù)的設(shè)置都只影響當(dāng)前綁定的紋理對象。最后刪除紋理對象的函數(shù)如下:

void glDeleteTextures(GLsizei n, GLuint *texture);

參數(shù)的意義與glGenTextures相同。不一定需要每次產(chǎn)生紋理對象使用后就刪除所有的紋理對象。多次調(diào)用glGenTextures的開銷較小,但多次調(diào)用glDeleteTextures會有導(dǎo)致一些延遲,原因是需要釋放大量的能存空間。在不再需要此紋理對象時,要把該紋理對象刪除,防止內(nèi)存泄露。

判斷紋理對象名稱是否可用可以通過下面的函數(shù)調(diào)用來判斷:

GLboolean glIsTexture(GLuint texture);

返回GL_TRUE代表可用,GL_FALSE代表不可用。

管理多個紋理

一般而言,在程序初始化時加載多個紋理對象,然后在渲染期間不斷地切換,在不再使用時刪除紋理對象。下面是一個通道tunnel的例子,此例在啟動時加載三個紋理對象,然后通過切換來繪制通道的磚墻,天花板和地板。此例中還演示了不同的mipmap模式,通過右鍵菜單來切換,通過上下箭頭鍵來在通道中移動,通過左右鍵來旋轉(zhuǎn)通道。

完整示例如下:

#include "gltools.h" #include <stdio.h>//定義宏常量 #define CEILING 0 #define BRICK 1 #define FLOOR 2 #define TEXTURENUM 3//紋理圖像的路徑 const char* texFileName[] = {"..\\ceiling.tga","..\\brick.tga","..\\floor.tga"};//紋理對象名稱 static GLuint textureName[TEXTURENUM];//旋轉(zhuǎn)與移動 static GLfloat yRot = 0.0f; static GLfloat zPos = 0.0f;//切換不同的紋理模式 void ProcessMenu(int value) {switch (value){case 0:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);break;case 1:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);break;case 2:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);break;case 3:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);break;case 4:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);break;case 5:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);break;case 6:if (gltIsExtSupported("GL_EXT_texture_filter_anisotropic")){//開啟各向異性過濾 GLfloat fLargest;glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);printf("anisotropic:%f\n", fLargest);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);}break;default:break;}glutPostRedisplay(); }void SetupRC() {glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//開啟深度測試,消除隱藏面,避免后畫的墻畫到前面來 glEnable(GL_DEPTH_TEST);//紋理圖像的信息 GLint iWidth, iHeight, iComponents;GLenum eFormat;//設(shè)置紋理環(huán)境 glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV, GL_REPLACE);//生成紋理對象 glGenTextures(TEXTURENUM, textureName);for (int i = 0; i < TEXTURENUM; ++i){void *pImage = gltLoadTGA(texFileName[i], &iWidth, &iHeight, &iComponents, &eFormat);if (pImage){//綁定紋理對象,生成mipmap glBindTexture(GL_TEXTURE_2D, textureName[i]);gluBuild2DMipmaps(GL_TEXTURE_2D, iComponents, iWidth, iHeight, eFormat, GL_UNSIGNED_BYTE, pImage);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);}free(pImage);}glEnable(GL_TEXTURE_2D);}void ShutdownRC() {//最后刪除紋理對象 glDeleteTextures(TEXTURENUM, textureName); }void RenderScene() {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPushMatrix();//移動和旋轉(zhuǎn)glTranslatef(0.0f, 0.0f, zPos);glRotatef(yRot, 0.0f, 1.0f, 0.0f);for(GLfloat z = -60.0f; z <= 0.0f; z += 10.0f){//綁定地板紋理繪制地板,注意glBeindTexture在glBegin和glEnd中是無效的 glBindTexture(GL_TEXTURE_2D, textureName[FLOOR]);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0f, -10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(-10.0f, -10.0f, z + 10.0f);glTexCoord2f(1.0f, 1.0f);glVertex3f(10.0f, -10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(10.0f, -10.0f, z);glEnd();//綁定天花板紋理 glBindTexture(GL_TEXTURE_2D, textureName[CEILING]);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0f, 10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(-10.0f, 10.0f, z + 10.0f);glTexCoord2f(1.0f, 1.0f);glVertex3f(10.0f, 10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(10.0f, 10.0f, z);glEnd();//綁定磚墻的紋理 glBindTexture(GL_TEXTURE_2D, textureName[BRICK]);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0f, -10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(-10.0f, 10.0f, z);glTexCoord2f(1.0f, 1.0f);glVertex3f(-10.0f, 10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(-10.0f, -10.0f, z + 10.0f);glTexCoord2f(0.0f, 0.0f);glVertex3f(10.0f, -10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(10.0f, 10.0f, z);glTexCoord2f(1.0f, 1.0f);glVertex3f(10.0f, 10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(10.0f, -10.0f, z + 10.0f);glEnd();}//GLclampf prioritize[TEXTURENUM] = {0.0f, 0.0f, 1.0f};//glPrioritizeTextures(TEXTURENUM, textureName, prioritize);//GLboolean isResident[TEXTURENUM];//if (glAreTexturesResident(TEXTURENUM, textureName, isResident))//{// printf("all texture is resident\n");//}//else//{// printf("texture resident is : %d %d %d", isResident[0], isResident[1], isResident[2]);//} glPopMatrix();glutSwapBuffers(); }void ChangeSize(GLsizei w, GLsizei h) {if (h == 1)h = 0;glViewport(0, 0, w, h);GLfloat aspect = (GLfloat)w/(GLfloat)h;glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(35.5, aspect, 1.0, 150.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glutPostRedisplay(); }void SpecialKey(int value, int x, int y) {if (value == GLUT_KEY_LEFT){yRot += 0.5f;}if (value == GLUT_KEY_RIGHT){yRot -= 0.5f;}if (value == GLUT_KEY_UP){zPos += 0.5f;}if (value == GLUT_KEY_DOWN){zPos -= 0.5f;}if (yRot > 365.5f){yRot = 0.0f;}glutPostRedisplay(); }int main(int arg, char **argv) {glutInit(&arg, argv);glutInitDisplayMode(GL_RGB | GL_DOUBLE | GL_DEPTH);glutInitWindowSize(800, 600);glutCreateWindow("tunel");glutReshapeFunc(ChangeSize);glutDisplayFunc(RenderScene);glutSpecialFunc(SpecialKey);glutCreateMenu(ProcessMenu);glutAddMenuEntry("GL_NEAREST", 0);glutAddMenuEntry("GL_LINEAR", 1);glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST", 2);glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 3);glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 4);glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);glutAddMenuEntry("ANISOTROPIC", 6);glutAttachMenu(GLUT_RIGHT_BUTTON);SetupRC();glutMainLoop();ShutdownRC();return 0; }

?

GL_NEAREST效果圖(紋理比較銳利):

GL_LINEAR_MIPMAP_LINEAR效果圖(線性插值后的紋理過渡較平滑):

在我們程序初始化時,生成了多個紋理對象,加載了多個紋理。這樣我們在使用時就非常的方便,只要通過glBindTexutre切換紋理就可以了。使用完之后就釋放紋理。

for(GLfloat z = -60.0f; z <= 0.0f; z += 10.0f){//綁定地板紋理繪制地板,注意glBeindTexture在glBegin和glEnd中是無效的 glBindTexture(GL_TEXTURE_2D, textureName[FLOOR]);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0f, -10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(-10.0f, -10.0f, z + 10.0f);glTexCoord2f(1.0f, 1.0f);glVertex3f(10.0f, -10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(10.0f, -10.0f, z);glEnd();//綁定天花板紋理 glBindTexture(GL_TEXTURE_2D, textureName[CEILING]);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0f, 10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(-10.0f, 10.0f, z + 10.0f);glTexCoord2f(1.0f, 1.0f);glVertex3f(10.0f, 10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(10.0f, 10.0f, z);glEnd();//綁定磚墻的紋理 glBindTexture(GL_TEXTURE_2D, textureName[BRICK]);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex3f(-10.0f, -10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(-10.0f, 10.0f, z);glTexCoord2f(1.0f, 1.0f);glVertex3f(-10.0f, 10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(-10.0f, -10.0f, z + 10.0f);glTexCoord2f(0.0f, 0.0f);glVertex3f(10.0f, -10.0f, z);glTexCoord2f(1.0f, 0.0f);glVertex3f(10.0f, 10.0f, z);glTexCoord2f(1.0f, 1.0f);glVertex3f(10.0f, 10.0f, z + 10.0f);glTexCoord2f(0.0f, 1.0f);glVertex3f(10.0f, -10.0f, z + 10.0f);glEnd();}

?

tunnel示例中,切換mipmap紋理過濾器時,只修改了縮小過濾器

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

典型的情況下,在OpenGL選擇了最大的可用mip層之后,就沒有更大的mip層可供選擇了。這相當(dāng)于設(shè)置了一條門檻,更大的圖形也只能使用這個mip層,沒有更大的mip層了。

常駐紋理

在大多數(shù)的OpenGL實現(xiàn)中,都提供了一定數(shù)量的常駐紋理來提高性能。顯卡的內(nèi)存(顯存)是有限的,在紋理切換中當(dāng)顯存不夠時,就要把一些紋理數(shù)據(jù)從顯存中移除(暫時存放到硬盤或內(nèi)存中)。

為了優(yōu)化性能,OpenGL會自動的把最經(jīng)常使用的紋理保存在顯存中作為常駐紋理。判斷當(dāng)前紋理是否是常駐紋理,通過下面的函數(shù)調(diào)用來測試:

GLboolean glAreTexturesResident(GLsizei n, const GLuint *texture, GLboolean *residences);

第一個參數(shù)是紋理對象的個數(shù),第二是紋理對象名稱數(shù)組,第三個是輸出參數(shù),記錄著對應(yīng)的紋理是否是常駐紋理。如果所有的紋理對象都是常駐紋理則glAreTexutresResident返回GL_TRUE。

紋理優(yōu)先級

默認情況下,OpenGL實現(xiàn)是使用最經(jīng)常使用(MFFU)來決定紋理是否常駐顯存。如果最經(jīng)常使用的紋理很小,而大紋理不經(jīng)常使用,那么就會導(dǎo)致小紋理常駐顯存,而大紋理卻經(jīng)常被移除。為了避免此問題,我們可以手動設(shè)置紋理的優(yōu)先級。通過下面的函數(shù)調(diào)用:

void glPrioritizeTextures(GLsizei n, const GLuint *texture, const GLclampf *priorites);

第一個參數(shù)是紋理對象的個數(shù),第二個是紋理名稱數(shù)組,第三個是紋理的優(yōu)先級參數(shù),范圍為[0.0,1.0]。低優(yōu)先級告訴OpenGL當(dāng)顯存不夠時有限考慮移除此低優(yōu)先級的紋理。示例:

GLclampf prioritize[TEXTURENUM] = {0.0f, 0.0f, 1.0f};
glPrioritizeTextures(TEXTURENUM, textureName, prioritize);
GLboolean isResident[TEXTURENUM];
if (glAreTexturesResident(TEXTURENUM, textureName, isResident))
{
printf("all texture is resident\n");
}
else
{
printf("texture resident is : %d %d %d", isResident[0], isResident[1], isResident[2]);
}

回顧

在紋理這一章,我們學(xué)習(xí)如何加載紋理glTexImage,設(shè)置紋理參數(shù)glTexParameter,設(shè)置紋理環(huán)境glTexEnv,使用mipmap,管理紋理對象,多紋理的使用和切換,紋理過濾器等等。詳細的介紹了紋理的各種參數(shù)。

代碼以及數(shù)據(jù)紋理和庫都在此地址可以獲取(上面的示例為tunnel工程):

https://github.com/sweetdark/openglex

轉(zhuǎn)載于:https://www.cnblogs.com/cack/p/4972806.html

總結(jié)

以上是生活随笔為你收集整理的【转】OpenGL超级宝典笔记——纹理映射Mipmap的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。