接著上一篇文章的內(nèi)容,本文主要分析如何將紋理映射到多邊形和物體上,會包含幾種紋理映射的方式。
準備好了紋理下面我們分析如何進行映射,將紋理數(shù)據(jù)映射到具體的物體上去。紋理坐標如下圖所示。
假設圖中的正方向就是我們要將紋理映射上去的物體(地面),那么我們需要按照圖中的表示,為每個頂點指定一個紋理坐標,也稱之為UV坐標,它的橫向為s軸,縱向圍t軸,如下圖所示。關于st和uv坐標可以參考一些3D圖形學相關知識。
那么下面我們就按照圖中的指示來為地面創(chuàng)建一個紋理坐標數(shù)組和緩沖區(qū),代碼如下:
byte[] tcs = {0,0, 1,0, 0,1, 1,1};
tcsBuf = ByteBuffer.allocateDirect(tcs.length);
tcsBuf.put(tcs).rewind();
準備好紋理的uv坐標之后,下面是最后一步,如何繪制該物體及紋理。代碼如下:
public void draw()
{
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_BYTE, 0, vertsBuf); // use floor verts
gl.glTexCoordPointer(2, GL10.GL_BYTE, 0, tcsBuf); // use tex coords
gl.glEnable(GL10.GL_TEXTURE_2D);
setTexture();
gl.glNormal3f( 0, 1.0f, 0); // facing up
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisable(GL10.GL_TEXTURE_2D); // switch off texturing
} // end of draw()
private void setTexture()
{
gl.glBindTexture(GL10.GL_TEXTURE_2D, texNames[0]); // use the tex name
// specify the texture for the currently bound tex name
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGB, imWidth, imHeight, 0,
GL10.GL_RGB, GL10.GL_UNSIGNED_BYTE, texBuf);
// set the minification/magnification techniques
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
} // end of setTexture()
其中大部分代碼我們已經(jīng)接觸過,標注為紅色的是需要我們解釋的,glEnableClientState函數(shù)就是允許我們設置紋理坐標數(shù)組,而函數(shù)glTexCoordPointer就是將前面準備的紋理坐標緩沖區(qū)告訴Opengl,這樣在繪制圖形時,Opengl會自動的對紋理進行處理,并展現(xiàn)出來。
運行結果如下圖所示。
圖中的地面就是我們繪制的一個四邊形,然后給映射了一個地面的紋理貼圖上去形成的。這里我們是直接將一整張圖給映射上去了,那么我們是否可以只映射圖像的一部分呢?答案是肯定的,我們只需要改動UV坐標即可。UV坐標對應如下圖所示。
這樣應該很好理解,相當于我們只是映射了圖像上的0.25到0.75之間的部分(整個圖像的寬度和高度為1),即圖像的中間部分。當然你同樣可以更改這個坐標,來調(diào)整自己需要映射的部分,這在實際的游戲開發(fā)過程中是經(jīng)常使用的,尤其是一些2D游戲的開發(fā),會將很多小的圖片放置到一個大的圖片之上,做成一個圖片集,就可以通過這種方式來確定需要映射圖片集中的哪一個小的圖塊。按照上圖的指示,我們將代碼需要改成float類型的數(shù)據(jù)即可,如下所示。
float[] tcs = {0.25f,0.25f,0.75f,0.25f,0.25f,0.75f,0.75f,0.75f};
tcsBuf = ByteBuffer.allocateDirect(tcs.length*4).asFloatBuffer();
tcsBuf.put(tcs).rewind();
/////
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, tcsBuf);
運行效果如下圖所示。
和第一個效果圖相比很明顯的紋理只去了圖像的中間一部分,上面的兩種方式都是將紋理映射到一個四邊形上,但是在Opengl ES中最基本的應該是三角形,我們是否可以將紋理映射到三角形上呢,同樣可以,對于三角形的紋理示意圖如下所示。
就這樣,同樣的步驟適合于幾何體中任何三角形,而且你甚至可以通過非常規(guī)方式的映射來扭曲紋理,產(chǎn)生各種特殊的效果??偠灾?,紋理上的任何一點都可以映射到多邊形的任何一點?;蛘邠Q而言之,你可以對任何地點(u,v)使用任何(s,t)而OpenGL ES則為你進行映射。