Cocos2dx-OpenGL ES2.0教程:紋理貼圖(6)
在上一篇文章中,我們介紹瞭如何繪製一個立方體,裡面涉及的知識點有VBO(Vertex Buffer Object)、IBO(Index Buffer Object)和MVP(Modile-View-Projection)變換。
本文將在教程4的基礎之上,新增紋理貼圖支援。最後,本文會把紋理貼圖擴充套件至3D立方體上面。
基本方法
當我們把一張圖片載入到記憶體裡面之後,它是不能直接被GPU繪製出來的,紋理貼圖過程如下:
首先,我們為之前的頂點新增紋理座標屬性並傳到vertex shader裡面去,然後把記憶體裡面的紋理傳給GPU,最後,在fragment shader裡面通過取樣器,就可以根據vertex shader傳遞過來的紋理座標把紋理上面的顏色值用插值的方式對映到每一個畫素上去。
接下來,讓我們看看具體怎麼做。
準備紋理座標(紋理座標也叫UV座標)
首先,我們需要修改我們的頂點屬性結構體,新增一個紋理座標屬性(TexCoord):
1 2 3 4 5 |
typedef struct { float Position[2]; float Color[4]; float TexCoord[2]; } Vertex; |
接下來,需要修改頂點陣列的值,主要就是新增UV座標:
1 2 3 4 5 6 7 |
Vertex data[] = { { {-1,-1},{0,1,0,1},{0,1}}, { {1,-1 |
注意,我們的紋理座標的(0,0)點在圖片的左上角,這個與OpenGL裡面的左下角是(0,0)有所區別。所以為了讓我們的圖片顯示正常,我們在指定左下角頂點(-1,-1)的時候,它對應的紋理座標應該是(0,1)。其它的座標點以此類推。
GLuint TexCoordLocation = glGetAttribLocation(glProgram->getProgram(), "a_coord"); glEnableVertexAttribArray glVertexAttribPointer(TexCoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex,TexCoord)); |
生成紋理
首先,我們在標頭檔案裡面定義一個紋理的控制代碼:
1
|
GLuint textureId;
|
然後是生成紋理:
1 textureId = Director::getInstance()->getTextureCache()->addImage("HelloWorld.png")->getName(); |
接下來,我需要處理Shader了。
修改Shader
首先,修改vertex shader,新增紋理座標屬性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
attribute vec2 a_position; attribute vec4 a_color; attribute vec2 a_coord; varying vec4 v_fragmentColor; varying vec2 v_coord; void main() { gl_Position = CC_MVPMatrix * vec4(a_position.xy,0,1); v_fragmentColor = a_color; v_coord = a_coord; } |
因為紋理座標最終要傳遞到fragment shader裡面去,所以需要定義一個varing
vec2 v_coord
變數。
接下來是fragment shader的程式碼:
1 2 3 4 5 6 7 8 9 10 |
varying vec4 v_fragmentColor; varying vec2 v_coord; uniform vec4 u_color; void main() { gl_FragColor = v_fragmentColor * texture2D(CC_Texture0,v_coord); } |
這邊也定義了一個同樣的varing變數,同時我們看到有一個texture2D函式,它可以通過CC_Texture0這個取樣器和紋理座標(v_coord)計算出對應的顏色值。
修改draw call
在呼叫draw call之前,我們需要繫結紋理。我們只需要在glDrawElements方法之前呼叫下列方法就可以了:
1
|
GL::bindTexture2D(textureId);
|
執行結果
接下來,我們需要把立方體的六個面都新增這張紋理。
讓立方體不再裸奔
這個過程大部分程式碼都是一樣的,惟一的區別就是頂點陣列的修改,我們需要為每一個面的頂點都指定UV座標:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#define TEX_COORD_MAX 1 Vertex Vertices[] = { // Front { {1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {-1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, -1, 0}, {0, 0, 0, 1}, {0, 0}}, // Back { {1, 1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {-1, -1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {1, -1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, 1, -2}, {0, 0, 0, 1}, {0, 0}}, // Left { {-1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {-1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {-1, 1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, -1, -2}, {0, 0, 0, 1}, {0, 0}}, // Right { {1, -1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {1, 1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {1, 1, 0}, {0, 0, 1, |