基础图形绘制
之前讲解过,OpenGL ES中,只提供了3种基本图形:点、线、三角形。而其他我们熟知的图形,都是基于这3种基本图形处理拼接合成的。那么本章节我们先从OpenGL中给我们提供的3种基础图形讲起,再介绍下其他图形的绘制。
基础图形绘制API
/**
* 使用顶点数据绘制图形
*/
GLES20.glDrawArrays(int mode, int first, int count);
基本上,很多场景下我们都使用这个方法来进行图形的绘制,这个方法通过调用GLES20.glVertexAttribPointer传递进去的顶点数据来绘制目标图形。相关参数作用如下
- mode:绘制模式,控制绘制点、线段、三角形以及其具体的连接方式
- first:从顶点数据读取数据的起点位置(以点作为单位,而非向量)
- count:绘制的顶点数(以点作为单位,而非向量)
废话说明:以点作为单位,而非向量,也就是说无论顶点数组是用x、y两个向量来标识,或者是用x、y、z、w来标识,最终都是以一个点的距离来控制绘制。主要原因是这里是传递给GL层的,而GL层的坐标是vec4的,和我们从java层传进去的无关,毕竟没传递的是有默认值的。
当前我们有个案例,按顺序有A、B、C、D、E、F一共6个点。
而mode的具体参数值如下:
参数 | 类型 | 作用 | 案例图形 |
---|---|---|---|
GL_POINTS | 点 | 绘制独立的点 | A、B、C、D、E、F |
GL_LINES | 线段 | 每2个点构成一条线段 | AB、CD、EF |
GL_LINE_LOOP | 线段 | 按顺序将所有的点连接起来,包括首位相连 | AB、BC、CD、DE、EF、FA |
GL_LINE_STRIP | 线段 | 按顺序将所有的点连接起来,不包括首位相连 | AB、BC、CD、ED、EF |
GL_TRIANGLES | 三角形 | 每3个点构成一个三角形 | ABC、DEF |
GL_TRIANGLE_STRIP | 三角形 | 相邻3个点构成一个三角形,不包括首位两个点 | ABC、BCD、CDE、DEF |
GL_TRIANGLE_FAN | 三角形 | 第一个点和之后所有相邻的2个点构成一个三角形 | ABC、ACD、ADE、AEF |
案例图示
GL_POINTSGL_LINES
GL_LINESGL_LINE_LOOP
GL_LINE_LOOP.gifGL_LINE_STRIP
GL_LINE_STRIP.gifGL_TRIANGLES
GL_TRIANGLES.gifGL_TRIANGLE_STRIP
GL_TRIANGLE_STRIP.gifGL_TRIANGLE_FAN
GL_TRIANGLE_FAN.gif多边形绘制
实心的多边形我们可以通过三角形拼接而成来实现,非实心的则可以通过线段拼接实现。具体效果如下图,黄色部分为实心多边形,红线为非实心多边形。当边数足够多的时候,多边形便接近于圆形。
polygon
关键代码实现如下:
/**
* 多边形的顶点数,即边数
*/
private int mPolygonVertexCount = 3;
/**
* 绘制所需要的顶点数
*/
private float[] mPointData;
/**
* 多边形顶点与中心点的距离
*/
private static final float RADIUS = 0.5f;
private void updateVertexData() {
// 边数+中心点+闭合点;一个点包含x、y两个向量
mPointData = new float[(mPolygonVertexCount + 2) * 2];
// 组成多边形的每个三角形的中心点角的弧度
float radian = (float) (2 * Math.PI / mPolygonVertexCount);
// 中心点
mPointData[0] = 0f;
mPointData[1] = 0f;
// 多边形的顶点数据
for (int i = 0; i < mPolygonVertexCount; i++) {
mPointData[2 * i + 2] = (float) (RADIUS * Math.cos(radian * i));
mPointData[2 * i + 1 + 2] = (float) (RADIUS * Math.sin(radian * i));
}
// 闭合点:与多边形的第一个顶点重叠
mPointData[mPolygonVertexCount * 2 + 2] = (float) (RADIUS * Math.cos(0));
mPointData[mPolygonVertexCount * 2 + 3] = (float) (RADIUS * Math.sin(0));
mVertexData = ByteBufferUtil.createFloatBuffer(mPointData);
mVertexData.position(0);
GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT,
false, 0, mVertexData);
}
private void drawShape() {
GLES20.glUniform4f(uColorLocation, 1.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, mPolygonVertexCount + 2);
}
思考与推论
上面的示例图中,在onDrawFrame里,同时绘制了点、线、三角形,也就是多次调用glDrawArrays,并且绘制出来了。
我们暂时定义glDrawArrays是进行一次图元组装,也就是绘制一个图层,那么一次onDrawFrame只绘制一帧,而这一帧可以绘制多种图元,多个图层。
也就是:一次只绘制一帧,但是一帧可以绘制多个图层。
参考
见Android OpenGL ES学习资料所列举的博客、资料。
GitHub代码工程
本系列课程所有相关代码请参考我的GitHub项目GLStudio。
课程目录
本系列课程目录详见 简书 - Android OpenGL ES教程规划
网友评论