),从而使得纹理的外观更为锐利,代价是纹理处理的开销大一些。
?
glTexImage, glTexSubImage和gluBuildMipmaps这些函数的调用消耗的时间特别多。这些函数大量的移动内存,有时需要重新调整数据的格式来适应一些内部的表示。在纹理之间切换或者重新加载不同的纹理图片会带来较大的性能开销。
为了减少这些开销,我们可以使用纹理对象。纹理对象允许你一次性加载多个纹理状态(包括纹理图像),然后在它们之间快速切换。纹理状态由当前绑定的纹理对象来维护。纹理的名称由unsigned int类型来标识。使用下面的函数来生成一定数量的纹理对象:
void glGenTextures(GLsizei n, GLuint *textures);
上面的函数调用指定了纹理对象的数量,和存储纹理对象名称的数组。我们可以通过纹理对象名称来操作纹理状态。绑定其中的一个纹理状态的函数调用如下:
void glBindTexture(GLenum target, GLuint texture);
target参数必须是GL_TEXTURE_1D,GL_TEXTURE_2D或者GL_TEXTURE_3D.texture是纹理名称指定要绑定的纹理对象。在此函数之后,纹理图像的加载和纹理参数的设置都只影响当前绑定的纹理对象。最后删除纹理对象的函数如下:
void glDeleteTextures(GLsizei n, GLuint *texture);
参数的意义与glGenTextures相同。不一定需要每次产生纹理对象使用后就删除所有的纹理对象。多次调用glGenTextures的开销较小,但多次调用glDeleteTextures会有导致一些延迟,原因是需要释放大量的能存空间。在不再需要此纹理对象时,要把该纹理对象删除,防止内存泄露。
判断纹理对象名称是否可用可以通过下面的函数调用来判断:
GLboolean glIsTexture(GLuint texture);
返回GL_TRUE代表可用,GL_FALSE代表不可用。
?
一般而言,在程序初始化时加载多个纹理对象,然后在渲染期间不断地切换,在不再使用时删除纹理对象。下面是一个通道tunnel的例子,此例在启动时加载三个纹理对象,然后通过切换来绘制通道的砖墙,天花板和地板。此例中还演示了不同的mipmap模式,通过右键菜单来切换,通过上下箭头键来在通道中移动,通过左右键来旋转通道。
完整示例如下:
GL_NEAREST效果图(纹理比较锐利):

GL_LINEAR_MIPMAP_LINEAR效果图(线性插值后的纹理过渡较平滑):

在我们程序初始化时,生成了多个纹理对象,加载了多个纹理。这样我们在使用时就非常的方便,只要通过glBindTexutre切换纹理就可以了。使用完之后就释放纹理。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
?
在大多数的OpenGL实现中,都提供了一定数量的常驻纹理来提高性能。显卡的内存(显存)是有限的,在纹理切换中当显存不够时,就要把一些纹理数据从显存中移除(暂时存放到硬盘或内存中)。
为了优化性能,OpenGL会自动的把最经常使用的纹理保存在显存中作为常驻纹理。判断当前纹理是否是常驻纹理,通过下面的函数调用来测试:
GLboolean glAreTexturesResident(GLsizei n, const GLuint *texture, GLboolean *residences);
第一个参数是纹理对象的个数,第二是纹理对象名称数组,第三个是输出参数,记录着对应的纹理是否是常驻纹理。如果所有的纹理对象都是常驻纹理则glAreTexutresResident返回GL_TRUE。
?
默认情况下,OpenGL实现是使用最经常使用(MFFU)来决定纹理是否常驻显存。如果最经常使用的纹理很小,而大纹理不经常使用,那么就会导致小纹理常驻显存,而大纹理却经常被移除。为了避免此问题,我们可以手动设置纹理的优先级。通过下面的函数调用:
void glPrioritizeTextures(GLsizei n, const GLuint *texture, const GLclampf *priorites);
第一个参数是纹理对象的个数,第二个是纹理名称数组,第三个是纹理的优先级参数,范围为[0.0,1.0]。低优先级告诉OpenGL当显存不够时有限考虑移除此低优先级的纹理。示例:
?
在纹理这一章,我们学习如何加载纹理glTexImage,设置纹理参数glTexParameter,设置纹理环境glTexEnv,使用mipmap,管理纹理对象,多纹理的使用和切换,纹理过滤器等等。详细的介绍了纹理的各种参数。