利用前一章的方法创建的三维物体,仅仅从颜色和建模方面去考虑的话,和实际的物体相差还是很大。因为现实世界中的物体并不是完全平滑的,在物体的表面有各种各样的图案,例如墙面的砖块、地面的木板纹路、衣服上的绣花、粗糙的桔子皮等等。这些效果是无法使用建模方法创造出来的。
将图案映射到物体的表面,显示出真实物体的模样,这种方法叫做纹理映射(Texture Mapping),也称作纹理贴图。
通常纹理就象位图一样,是一个二维的颜色值的阵列,其中每一个单个的颜色值称为纹理元素,类似于像素的的说法,可以称之为纹素(texel)。每一个纹素在纹理中都有唯一的地址,纹素的地址可以看作是分别标为U和V的行和列。
一般定义U=[0,1],V=[0,1]的正方形区域为纹理空间,但是实际上是用的纹理并不限于此。纹理坐标就是纹素在纹理空间中的坐标值,当纹理被映射到三维物体上时,纹理坐标就被映射到空间坐标上,并转换成屏幕像素坐标显示出来。OpenGL为了提高效率,直接把纹理坐标映射到屏幕坐标上。
纹理坐标是用glTexCoord*()函数来表示的,其原型如下:
void glTexCoord{[1][2][3][4]}{[d][f][i][s]}[v](TYPE coords);
纹理坐标可以表示成一、二、三或四维形式,称为s,t,r和q坐标,对应的函数后缀分别为1、2、3和4,函数的参数个数和后缀相同。其中s用于一维纹理坐标,s、t用于二维纹理坐标,q用于齐次坐标,r通常忽略。实际中最常用的是glTexCoord2*()。s、i、f、d分别表示参数的类型是GLshort 、GLint、GLfloat和GLdouble。
在应用纹理映射时,需要在使用glVertex设置顶点坐标前给出顶点的纹理坐标。下面以一个方形纹理映射到四边形上说明纹理的坐标使用。假设纹理图像为图5-1所示,则通过纹理坐标的变化可以得到四种典型的映射效果。
图5-1 纹理图像
整个纹理全部映射到四边形上。
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
效果如图5-2所示,和纹理图像是一样的。
图5-2 纹理映射效果一
如同砖块的图像纹理映射在墙面上
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(4.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(4.0f, 3.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 3.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
结果将3行、4列的纹理映射到四边形上,如图5-3所示。
图5-3 纹理映射效果二
部分映射是仅仅将纹理图像的一部分映射到多边形上,这样就有一部分纹理看不到,如图5-4所示。
glBegin(GL_QUADS);
glTexCoord2f(0.2f, 0.2f);glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(0.7f, 0.2f);glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(0.7f, 0.7f);glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.2f, 0.7f);glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
上述代码的结果将纹理中心部分映射到四边形上。
图5-4 纹理映射效果三
镜面映射实际上是将纹理左右或上下颠倒映射。
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(-2.0f, 0.0f);glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(-2.0f, -2.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, -2.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
结果映射后的图像和纹理图像相比,左右和上下均翻转了180度,并且分为2行和2列,如图5-5所示。
图5-5 纹理映射效果四
OpenGL应用纹理的过程有如下几个步骤:
1、取得纹理图像数据,可以从图像文件中加载;
2、调用glGenTextures生成一个纹理名称;
3、调用glBindTexture绑定纹理;
4、调用glTexImage2D或gluBuild2DMipmaps生成纹理;
5、调用glTexParameter设置纹理滤波方式;
6、通过glEnable(GL_TEXTURE_2D)启用纹理映射;
7、在使用glVertex设置顶点坐标前调用glTexCoord设置该顶点的纹理坐标值;
8、显示映射纹理后的图形。