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
    以一个点为三角形公共顶点,组成一系列相邻的三角形。

你可能感兴趣的:(Android)