5.OpenGL学习之纹理映射

纹理映射

  一个常用的添加表面细节的方法是将纹理模式映射到对象表面上。纹理模式可以由一个矩形数组进行定义,也可以用一个修改对象表面光强度值的过程来定义,这个方法 称为纹理映射,而纹理可以定义成一维、二维或三维图案。任意纹理描述称为纹理空间,用0到1.0范围的纹理坐标来表示。

纹理图案

1、一维图案

  一维纹理图案可以用颜色值的单足码数组指定,用来定义线性纹理空间的一系列颜色。例如,可以用足码为0到95的数组建立32个RGB颜色的一张表。该数组最前面三个元素存储第一个颜色的RGB分量,下面三个元素存储第二个颜色的RGB分量,以此类推。对于一个线性图案,纹理空间用单个s坐标值表示。对RGB颜色描述,值s=0.0指定数组中的第一组三元素RGB颜色,值s=1.0指定最后一组的三个RGB颜色分量。用单下标颜色数组指定的一维RGBA纹理图案的参数由下列语句指定:

    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, nTexColors, 0, 
                               dataFormat, dataType, lineTexArray)

第一个参数设定为符号常量GL_TEXTURE_1D来指出正在为一个一维对象即一条线段定义一个纹理数组。第二个参数设为0表示该数组不是某个大纹理数组的缩减。第三个参数设为符号常量GL_RGBA表示该纹理图案的每一颜色用RGBA四个值指定。第四个参数nTexColors赋以一个正整数,用于指出该线性纹理图案的颜色数量。第五个参数设为0表示不希望在纹理周围有边界,设为1则该纹理图案在显示时有一个单像素宽的边界,用来将该图案与相邻图案融合。
  我们可以将一个纹理的多个副本或该纹理颜色的任意相邻子集映射到场景的一个对象上。当一组纹理元素映射到一个或多个像素区域时,纹理元素的边界通常与像素边界位置不对齐。一个像素区域可能包含在一个RGB(或RGBA)纹理元素中,也可能与多个纹理元素重叠。为了简化纹理映射时的计算,使用下列函数来给给出每一像素的最接近纹理元素的颜色。

glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

纹理子程序在必须放大纹理图案的一部分以适合指定的场景坐标范围时使用第一个函数,而在必须缩减纹理图案时使用第二个函数。要按重叠纹理颜色的线性混合方式来计算像素颜色,需要用符号常量GL_LINEAR替代GL_NEAREST 。
  通过将纹理坐标值赋给对象位置来将纹理图案用到场景中的对象上。一维纹理空间的具体的s值用下列函数来选择:

glTexCoor1*(sCoord);

该函数允许使用的后缀码是b(字节)、s(短整数)、i(整数)、f(浮点数)和d(双倍长浮点数),依赖于纹理坐标参数sCoord的数据类型。s坐标是一个状态参数,它应用于所有在其后定义的世界坐标位置。s坐标的默认值是0.0。

2、二维图案

  用于表面区域的纹理通常用矩形颜色图案定义,而在纹理空间的位置用二维(s,t)坐标值来指定。s和t的值在0到1.0之间变换。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, 
                          texHeight, 0, dataFormat, dataType, surTextArray);

存储在surfTexArray中的数组尺寸是4*宽*高。对于二维纹理图案,按自下而上次序设定纹理数组元素的颜色值。
  和一维图案一样,场景中的表面像素可以赋予最近纹理颜色或一个插值纹理颜色。我们可以用在一维纹理中使用的同样两个glTexParameter函数来选择这些参数中的一个。一个函数指定在放大纹理图案以适合一个坐标范围时使用的选项, 而另一个函数指定在缩减纹理时使用的选项。一个纹理图案可以在一个方向拉长而在另一个方向压缩。例如,下面的语句构成了使用最近颜色显示投影表面位置的纹理子程序。

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

要将一个插值纹理颜色赋给表面像素,可使用符号常量GL_LINEAR替代GL_NEAREST。
  二维纹理空间的一个坐标位置用下列函数来选择:

glTexCoor2*(sCoord, tCoord);

3、三维图案

  除了线性和表面图案外,我们还可以为空间三维区域的位置指定一组颜色,这些纹理称为体纹理图案。体纹理通过三维纹理空间(s, t, r)来指定。而一个三维空间在单位立方体内定义,其纹理坐标范围为0到1.0。三维纹理空间函数是二维纹理空间函数的简单扩充。例如,一个没有边界的四足码RGBA纹理数组可用下列函数来建立:

glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, texWidth, texHeight, 
                        texDepth, 0, dataFormat, dataType, volTextArray);

该RGBA纹理颜色存储在volTextArray中,其中包含了4*texWidth*texHeight*texDepth个元素。
 下列语句可以使用最近纹理颜色显示像素:

glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

对于线性插值纹理颜色,可使用符号常量GL_LINEAR替代GL_NEAREST 。
  三维纹理空间的一个坐标位置用下列函数来选择:

glTexCoor3*(sCoord, tCoord, rCoord);

示例演示

  利用二维图案,将纹理映射到立方体的六个面, 同时立方体绕着x轴旋转。

void MyQGLWidget::drawCube()
{
    glRotatef(rotateAngle_, 1.0f, 0.0f, 0.0f);
    static const GLfloat P1[3] = { 1.0, 1.0, 1.0 };
    static const GLfloat P2[3] = { -1.0, 1.0, 1.0 };
    static const GLfloat P3[3] = { -1.0, -1.0, 1.0 };
    static const GLfloat P4[3] = { 1.0, -1.0, 1.0 };
    static const GLfloat P5[3] = { 1.0, 1.0, -1.0 };
    static const GLfloat P6[3] = { -1.0, 1.0, -1.0 };
    static const GLfloat P7[3] = { -1.0, -1.0, -1.0 };
    static const GLfloat P8[3] = { 1.0, -1.0, -1.0 };

    static const GLfloat * const coords[6][4] = {
        { P1, P2, P3 ,P4}, { P6, P5, P8, P7 }, { P2, P6, P7, P3 }, { P5, P1, P4, P8 },{P5, P6, P2, P1},{P4, P3, P7, P8}
    };

    static const GLfloat T1[2] = { 0.0f, 0.0f };
    static const GLfloat T2[2] = { 1.0f, 0.0f };
    static const GLfloat T3[2] = { 1.0f, 1.0f };
    static const GLfloat T4[2] = { 0.0f, 1.0f };

    static const GLfloat * const tCoords[4] = {T1, T2, T3, T4};

    for (int i = 0; i < 6; ++i) {
        glBegin(GL_QUADS);
        for (int j = 0; j < 4; ++j) {
            glTexCoord2f(tCoords[j][0], tCoords[j][1]);
            glVertex3f(coords[i][j][0], coords[i][j][1],
                       coords[i][j][2]);
        }
        glEnd();
    }
    rotateAngle_ += 0.5f;  
}

运行结果:

这里写图片描述

代码下载
OpenGL学习系列导航

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值