天天看點

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, , GL_RGBA, nTexColors, , 
                               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, , GL_RGBA, texWidth, 
                          texHeight, , 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, , GL_RGBA, texWidth, texHeight, 
                        texDepth, , 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_, , , );
    static const GLfloat P1[] = { , ,  };
    static const GLfloat P2[] = { -, ,  };
    static const GLfloat P3[] = { -, -,  };
    static const GLfloat P4[] = { , -,  };
    static const GLfloat P5[] = { , , - };
    static const GLfloat P6[] = { -, , - };
    static const GLfloat P7[] = { -, -, - };
    static const GLfloat P8[] = { , -, - };

    static const GLfloat * const coords[][] = {
        { 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[] = { ,  };
    static const GLfloat T2[] = { ,  };
    static const GLfloat T3[] = { ,  };
    static const GLfloat T4[] = { ,  };

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

    for (int i = ; i < ; ++i) {
        glBegin(GL_QUADS);
        for (int j = ; j < ; ++j) {
            glTexCoord2f(tCoords[j][], tCoords[j][]);
            glVertex3f(coords[i][j][], coords[i][j][],
                       coords[i][j][]);
        }
        glEnd();
    }
    rotateAngle_ += ;  
}
           

運作結果:

5.OpenGL學習之紋理映射紋理映射紋理圖案

代碼下載下傳

OpenGL學習系列導航

繼續閱讀