Android OpenGL ES 繪圖 -- 基礎元素
本文章為使用OpengGL繪製-點、線、面
點
準備工作在之前文章中已經介紹,本文直接繪圖
在 Android 系統中可以使用一個浮點數陣列來定義一個頂點,浮點數陣列通常放在一個 Buffer(java.nio)中來提高效能。
比如:下圖中定義了四個頂點和對應的 Android 頂點定義:
預設情況下,可視區域的四個頂點分別為v0(-1,1,0);v1(-1,-1,0)v2(1,-1,0);v3(1,1,0)(注:此座標有可能不為正方形)
// 清除螢幕和深度快取
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
//建立點座標(x,y,z),每三個數為一組
float vertices[] = {
-0.5f, 0.5f, 0.0f, // 0, Top Left
-0.5f, -0.5f, 0.0f, // 1, Bottom Left
0.5f, -0.5f, 0.0f, // 2, Bottom Right
0.5f, 0.5f, 0.0f, // 3, Top Right
};
為了提高效能,通常將這些陣列存放到 java.io 中定義的 Buffer 類中:
ByteBuffer vbb = ByteBuffer.allocateDirect (vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
有了頂點的定義,下面一步就是如何將它們傳給 OpenGL ES 庫,OpenGL ES 提供一個成為”管道 Pipeline ”的機制,這個管道定義了一些“開關”來控制 OpenGL ES 支援的某些功能,預設情況這些功能是關閉的,如果需要使用 OpenGL ES 的這些功能,需要明確告知 OpenGL “管道”開啟所需功能。因此對於我們的這個示例,需要告訴 OpenGL 庫開啟 Vertex buffer 以便傳入頂點座標 Buffer。要注意的使用完某個功能之後,要關閉這個功能以免影響後續操作:
//設定點的大小
gl.glPointSize(5f);
//開啟點座標管道
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//傳入點座標
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//根據點座標繪點
gl.glDrawArrays(GL10.GL_POINTS, 0, vertices.length/3);
//關閉點座標
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
線
OpenGL繪線,需根據點來繪製,以下示例中的點資料為上繪點的座標
新增繪線順序陣列
short[] indices = { 0, 1,
2, 0,
2, 3 };
為了提高效能,通常將這些陣列存放到 java.io 中定義的 Buffer 類中:
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
ShortBuffer indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
開始繪製
//開啟點座標管道
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//傳入點座標
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//根據點與繪線順序繪線
gl.glDrawElements(GL10.GL_LINES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
//關閉點座標
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
其中GL10.GL_LINES:
GL_LINES
頂點兩兩連線,為多條線段構成。
GL_LINE_STRIP
繪製一系列線段。
GL_LINE_LOOP
類同上,但是首尾相連,構成一個封閉曲線。
面
定義面的頂點的順序很重要 在拼接曲面的時候,用來定義面的頂點的順序非常重要,因為頂點的順序定義了面的朝向(前向或是後向),為了獲取繪製的高效能,一般情況不會繪製面的前面和後面,只繪製面的“前面”。雖然“前面”“後面”的定義可以應人而易,但一般為所有的“前面”定義統一的頂點順序(順時針或是逆時針方向)。
下面程式碼設定逆時針方法為面的“前面”:
gl.glFrontFace(GL10.GL_CCW);
開啟 忽略“後面”設定:
gl.glEnable(GL10.GL_CULL_FACE);
明確指明“忽略“哪個面的程式碼如下:
gl.glCullFace(GL10.GL_BACK);
繪製面與繪製線差不多,同樣先決定繪製時的順序
short[] indices = { 0, 1,
2, 0,
2, 3 };
為了提高效能,通常將這些陣列存放到 java.io 中定義的 Buffer 類中:
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
ShortBuffer indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
開始繪製
//開啟點座標管道
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//傳入點座標
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//根據點與繪線順序繪面
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
//關閉點座標
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
其中GL10.GL_TRIANGLES:
GL_TRIANGLES
每隔三個頂點構成一個三角形,為多個三角形組成。
GL_TRIANGLE_STRIP
每相鄰三個頂點組成一個三角形,為一系列相接三角形構成。
- GL_TRIANGLE_FAN
以一個點為三角形公共頂點,組成一系列相鄰的三角形。