本文章为使用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
每相邻三个顶点组成一个三角形,为一系列相接三角形构成。