基础图形绘制

之前讲解过,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_POINTS

GL_LINES

GL_LINES

GL_LINE_LOOP

GL_LINE_LOOP.gif

GL_LINE_STRIP

GL_LINE_STRIP.gif

GL_TRIANGLES

GL_TRIANGLES.gif

GL_TRIANGLE_STRIP

GL_TRIANGLE_STRIP.gif

GL_TRIANGLE_FAN

GL_TRIANGLE_FAN.gif

多边形绘制

实心的多边形我们可以通过三角形拼接而成来实现,非实心的则可以通过线段拼接实现。当边数足够多的时候,多边形便接近于圆形。

关键代码实现如下:

/**
 * 多边形的顶点数,即边数
 */
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只绘制一帧,而这一帧可以绘制多种图元,多个图层。
也就是:一次只绘制一帧,但是一帧可以绘制多个图层。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐