OpenGL中的贴图方式

时间:2022-09-10 17:00:34

 http://apps.hi.baidu.com/share/detail/54807724

OpenGL为我们提供了三种纹理——GL_TEXTURE_1D、GL_TEXTURE_2D和GL_TEXTURE_3D。它们分别表示1维纹理、2维纹理和3维纹理。无论是哪一中纹理,使用方法都是相同的:即先创建一个纹理对象和一个存储纹理数据的n维数组,在调用glTexImageND函数来传入相应的纹理数据。除此之外,我们可以一些函数来设置纹理的其他特性。

6.3.1 设置贴图模式

    OpenGL提供了3种不同的贴图模式:GL_MODULATE,GL_DECAL和GL_BLEND。默认情况下,贴图模式是GL_MODULATE,在这种模式下,OpenGL会根据当前的光照系统调整物体的色彩和明暗。第二种模式是GL_DECAL,在这种模式下所有的光照效果都是无效的,OpenGL将仅依据纹理贴图来绘制物体的表面。最后是GL_BLEND,这种模式允许我们使用混合纹理。在这种模式下,我们可以把当前纹理同一个颜色混合而得到一个新的纹理。我们可以调用glTexEnvi函数来设置当前贴图模式:

    glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,TextureMode);

    其中TextureMode就是想要设置的纹理模式,可以为GL_MODULATE,GL_DECAL和GL_BLEND中的任何一种。

    另外,对于GL_BLEND模式,我们可以调用

    glTexEnvfv(GL_TEXUTRE_ENV,GL_TEXTURE_ENV_COLOR,@ColorRGBA);

    其中,ColorRGBA为一个表示RGBA颜色的4维数组。

6.3.2 纹理滤镜

    在纹理映射的过程中,如果图元的大小不等于纹理的大小,OpenGL便会对纹理进行缩放以适应图元的尺寸。我们可以通过设置纹理滤镜来决定OpenGL对某个纹理采用的放大、缩小的算法。

    调用glTexParameter来设置纹理滤镜。如:

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILETER,MagFilter);//设置放大滤镜
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, MinFilter); //设置缩小滤镜

   上述调用中,第一个参数表明是针对何种纹理进行设置,第二个参数表示要设置放大滤镜还是缩小滤镜。第三个参数表示使用的滤镜。可以为下面的值之一:

表6.3-1 可使用的纹理滤镜
滤镜 描述
GL_NEAREST 取最邻近像素
GL_LINEAR 线性内部插值
GL_NEAREST_MIPMAP_NEAREST 最近多贴图等级的最邻近像素
GL_NEAREST_MIPMAP_LINEAR 在最近多贴图等级的内部线性插值
GL_LINEAR_MIPMAP_NEAREST 在最近多贴图等级的外部线性插值
GL_LINEAR_MIPMAP_LINEAR 在最近多贴图等级的外部和内部线性插值

    有关多贴图的内容,我们稍候将详细讲解。

    至此,我们已经可以产生一个纹理,并为它指定各种参数。但我们在绘制图元时必须进行纹理映射,才能将纹理贴在图元表面上。

6.4 纹理映射

6.4.1 纹理坐标

    要使用当前的纹理绘制图元,我们必须在绘制每个顶点之前为该顶点指定纹理坐标。只需调用

    glTexCoord2d(s:Double;t:Double);

    函数即可。其中,s、t是对于2D纹理而言的s、t坐标。对于任何纹理,它的纹理坐标都如同图6.4-1所示的那样:

OpenGL中的贴图方式

图6.4-1 纹理坐标

    对于任何纹理,无论纹理的真正大小如何,其顶端(左上角)的纹理坐标恒为(0,0),右下角的纹理坐标恒为(1,1)。也就是说,纹理坐标应是一个介于0到1之间的一个小数。

6.4.2 纹理缠绕

    前面提到,纹理坐标应位于0-1之间。那么当纹理坐标大于这个值会出现什么情况呢?

    我们可以对OpenGL进行设置,以决定当纹理坐标不位于这一区间时应采取的操作。我们可以指定两种操作:GL_CLAMP和GL_REPEAT。对于GL_CLAMP,超出纹理坐标的区域会使用纹理图像的边界颜色来代替,如图6.4-2所示。

OpenGL中的贴图方式

图6.4-2 GL_CLAMP 的工作方式

    而GL_REPEAT方式则是对纹理坐标进行重置而得到重复的图像。观察图6.4-3,你就能很容易地发现这一点。

OpenGL中的贴图方式

图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。

6.6 多贴图纹理

    多贴图纹理(Mip Mapping)为一个纹理对象生成不同尺寸的图像。在需要时,根据绘制图形的大小来决定采用的纹理等级或者在不同的纹理等级之间进行线性内插。使用多贴图纹理的好处在于消除纹理躁动。这种情况在所绘制的景物离观察者较远时常常发生(如图6.6-1和6.6-2)。由于多贴图纹理现在的渲染速度已经很快,以至于和普通纹理没有什么区别,我们现在一般都使用多贴图纹理。

OpenGL中的贴图方式 OpenGL中的贴图方式
图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);

来自:http://www.graphixer.com.cn/ShowWorks.asp?Type=1&ID=23