02-加载纹理图像文件
5.1 加载纹理图像文件
为了在OpenGL/GLSL中有效地完成纹理贴图,需要协调好以下几个不同的数据集和机制:
- 用于保存纹理图像的纹理对象(在本章中我们仅考虑2D图像);
- 一个特殊的统一采样器变量,以便顶点着色器可以访问纹理;
- 用于保存纹理坐标的缓冲区;
- 用于将纹理坐标传递给管线的顶点属性;
- 显卡上的纹理单元。
纹理图像可以是任何图像。它可以是人造的或者自然产生的事物的图片,例如布、草或行星表面;它也可以是几何图样,例如图5.1中的棋盘图样。在电子游戏和动画电影中,纹理图像通常用于给角色绘制面部和衣服,或者在像图5.1中的海豚等生物身上绘制皮肤。
图像通常存储在图像文件中,例如.jpg、.png、.gif或.tiff格式。为了使纹理图像可以被用于OpenGL管线中的着色器,我们需要从图像中提取颜色并将它们放入OpenGL纹理对象(用于保存纹理图像的内置OpenGL结构)中。
许多C++库可用于读取和处理图像文件,常见的选择包括Cimg、BoostGIL和Magick++。我们选择使用专为OpenGL设计的名为SOIL2 [SO17]的库,它基于曾经非常流行但现在已经过时的库SOIL。在附录A和附录B中介绍了SOIL2的安装步骤。
通常我们将纹理加载到OpenGL应用程序的步骤是:(a)使用SOIL2实例化OpenGL纹理对象并从图像文件中读入数据;(b)调用glBindTexture()以使新创建的纹理对象处于激活状态;(c)使用glTexParameter()函数调整纹理设置。最终获得的结果就是现在可用的OpenGL纹理对象的整型ID。
创建一个纹理对象,首先需要声明一个GLuint类型的变量。正如我们所看到的,这是一个用于保存OpenGL对象的整型ID引用的OpenGL类型。接下来,我们调用SOIL_load_OGL_texture()来实际生成纹理对象。SOIL_load_OGL_texture()函数接受图像文件名作为其参数之一(稍后将描述一些其他参数)。这些步骤在以下函数中实现:
GLuint loadTexture(const char *texImagePath) {
GLuint textureID;
textureID = SOIL_load_OGL_texture(texImagePath,
SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
if (textureID == 0) cout << "could not find texture file" << texImagePath << endl;
return textureID;
}
我们会经常使用这个函数,所以我们将它添加到Utils.cpp实用工具类中。这样,我们的C++应用程序就只需调用上述的loadTexture()函数来创建OpenGL纹理对象,如下所示。
GLuint myTexture = Utils::loadTexture("image.jpg");
其中image.jpg是纹理图像文件,myTexture是生成的OpenGL纹理对象的整型ID。这里支持多种图像文件类型,包括前面列出的所有图像文件类型。