1. 程式人生 > >OpenGL中的貼圖方式

OpenGL中的貼圖方式

OpenGL為我們提供了三種紋理——GL_TEXTURE_1D、GL_TEXTURE_2D和GL_TEXTURE_3D。它們分別表示1維紋理、2維紋理和3維紋理。無論是哪一中紋理,使用方法都是相同的:即先建立一個紋理物件和一個儲存紋理資料的n維陣列,在呼叫glTexImageN D函式來傳入相應的紋理資料。除此之外,我們可以一些函式來設定紋理的其他特性。

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所示的那樣:

圖6.4-1 紋理座標

    對於任何紋理,無論紋理的真正大小如何,其頂端(左上角)的紋理座標恆為(0,0),右下角的紋理座標恆為(1,1)。也就是說,紋理座標應是一個介於0到1之間的一個小數。

6.4.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。

6.6 多貼圖紋理

    多貼圖紋理(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);

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