2 纹理缠绕
前面提到,纹理坐标应位于0-1之间。那么当纹理坐标大于这个值会出现什么情况呢?
我们可以对OpenGL进行设置,以决定当纹理坐标不位于这一区间时应采取的操作。我们可以指定两种操作:GL_CLAMP和GL_REPEAT。对于GL_CLAMP,超出纹理坐标的区域会使用纹理图像的边界颜色来代替,如图6.4-2所示。
![]() |
图6.4-2 GL_CLAMP 的工作方式 |
而GL_REPEAT方式则是对纹理坐标进行重置而得到重复的图像。观察图6.4-3,你就能很容易地发现这一点。
![]() |
图6.4-3 GL_REPEAT 的工作方式 |
可以调用glTexParameter设置缠绕方式:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,WrapMode);//在s方向上的缠绕方式
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,WrapMode);//在t方向上的缠绕方式
其中,WrapMode可取GL_CLAMP或者GL_REPEAT。
4.纹理对象
创建和使用文理对象
在OpenGL中,我们使用glGenTextures创建纹理对象:
glGenTextures(Count:Integer;TexObjs:Pointer);
其中,Count是我们要创建的纹理数目,当我们只想创建一个纹理时,只需调用
var Texture:GLUint;
...
glGenTextures(1,@Texture);
这样,Texture变量中就存储了我们创建的纹理的ID号。
创建之后,我们使用glBindTexture将创建的纹理绑定到当前纹理。这样所有的纹理函数都将针对当前纹理。
glBindTexture(Texture:GLUint);
这样,我们就可以调用glTexParameter、glTexImage2D等函数来设置这个纹理对象了。
删除纹理对象
在纹理资源使用完毕后(一般是程序退出或场景转换时),一定要删除纹理对象,释放资源。
调用
glDeleteTextures(Count:Integer;TexObj:Pointer);
来删除纹理对象。例如
glDeleteTextures(1,@Texture);
5. 多贴图纹理
多贴图纹理(Mip Mapping)为一个纹理对象生成不同尺寸的图像。在需要时,根据绘制图形的大小来决定采用的纹理等级或者在不同的纹理等级之间进行线性内插。使用多贴图纹理的好处在于消除纹理躁动。这种情况在所绘制的景物离观察者较远时常常发生(如图6.6-1和6.6-2)。由于多贴图纹理现在的渲染速度已经很快,以至于和普通纹理没有什么区别,我们现在一般都使用多贴图纹理。
![]() | ![]() |
图6.6-1 GL_LINEAR滤镜下的远景 | 图6.6-1 使用多纹理贴图的远景 |
使用多贴图纹理并不麻烦。首先,我们需要创建不同等级(尺寸)的纹理图片。我们需要调用n次glTexImage2D函数,生成不同等级的纹理贴图。例如:
glTexImage2D(GL_TEXTURE_2D,0,3,8,8,0,GL_RGB,GL_UNSIGNED_BYTE,Pixels);
glTexImage2D(GL_TEXTURE_2D,1,3,4,4,0,GL_RGB,GL_UNSIGNED_BYTE,Pixels);
glTexImage2D(GL_TEXTURE_2D,2,3,2,2,0,GL_RGB,GL_UNSIGNED_BYTE,Pixels);
glTexImage2D(GL_TEXTURE_2D,3,3,1,1,0,GL_RGB,GL_UNSIGNED_BYTE,Pixels);
这些函数调用的第二个参数表示当前纹理的等级。0级的分辨率最大。之后,每一级的分辨率是上一级分辨率的一半。这样的函数调用应一直进行下去,直至图像的高度和宽度都为1。
但有时候,这样做总并不是很方便。我们可以借助一个glu函数帮我们自动生成这些多贴图纹理。只需要把生成纹理图像的函数调用由glTexImage2D改为gluBuild2DMipMaps即可:
gluBuild2DMipMaps(GL_TEXTURE_2D,3,Bit.Width,Bit.Height,0,GL_RGB,GL_UNSIGNED_BYTE,Pixels);
此外,还必须把纹理的滤镜改为MIP_MAP滤镜。例如:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);