使用Android OpenGL ES 2.0绘图之二:定义形状

传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229

         在OpenGLES view上能够定义所绘制图形的形状,是创建高端图形应用杰作的第一步。如果你不懂得OpenGL ES定义图形对象的一些基本知识,那么使用起来可能有一点棘手。

        这一节将介绍OpenGL ES相对于Android设备屏幕的坐标系,定义一个形状的基础知识,形状的外观,以及如何定义一个三角形和一个正方形。

1定义一个三角形

        OpenGL ES允许你使用三维空间坐标系来定义绘制对象。所以,在你想要绘制一个三角形之前,必须定义它的坐标。

         在OpenGL中,典型的方式是定义一个浮点类型的顶点数组存放各个顶点坐标。为了获得更高的效率,应该将这些坐标都存放到一个ByteBuffer中,ByteBuffer会被传入OpenGL ES图形管道进行处理。
class Triangle {

    private FloatBuffer vertexBuffer;

    // 设置每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    // 设置三角形顶点数组
    static float triangleCoords[] = { // 默认按逆时针方向顺序绘制
         0.0f,  0.622008459f, 0.0f,   // 顶
        -0.5f, -0.311004243f, 0.0f,   // 左底
         0.5f, -0.311004243f, 0.0f    // 右底
    };

    // 设置图形的RGB值和透明度
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public Triangle() {
        // 初始化顶点字节缓冲区,用于存放形状的坐标,
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (每个浮点数占用4个字节)
                triangleCoords.length * 4);
        // 设置使用设备硬件的原生字节序
        bb.order(ByteOrder.nativeOrder());

        // 从ByteBuffer中创建一个浮点缓冲区
        vertexBuffer = bb.asFloatBuffer();
        // 把坐标都添加到FloatBuffer中
        vertexBuffer.put(triangleCoords);
        // 设置buffer从第一个坐标开始读
        vertexBuffer.position(0);
    }
}

        默认情况下,OpenGL ES 假定GLSurfaceView帧的中心是坐标系[0,0,0](X,Y,Z),[1,1,0]是右上角,[-1,-1,0]是左下角。有关这个坐标系统的说明,请参阅OpenGL ES开发人员指南。
        注意这个形状的坐标是按逆时针方向定义的。绘制顺序很重要,因为它定义了哪个面是形状的正面,哪个面是反面。使用OpenGL ES的cullface特性,你可以只画正面不画反面。更多关于faces和culling的信息,请参阅OpenGL ES开发人员指南。

2定义一个正方形

        在OpenGL中定义三角形非常容易,如果想得到一个更为复杂的形状,比如说一个正方形,有很多方法可以做到,其中典型的做法是使用两个三角形集合而成。

        在此之后,需要分别为两个三角形按逆时针方向定义这些顶点,并且将这些坐标值都存放到一个ByteBuffer中。为了避免分别为两个三角形定义两个坐标数组,我们使用一个绘制列表来告诉OpenGL ES图形管道如果绘制这些顶点。下面就是这个形状的代码:
class Square {

    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;

    // 设置每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    static float squareCoords[] = { -0.5f,  0.5f, 0.0f,   // 左上
                                    -0.5f, -0.5f, 0.0f,   // 左下
                                     0.5f, -0.5f, 0.0f,   // 右下
                                     0.5f,  0.5f, 0.0f }; // 右上

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // 设置顶点的绘制顺序

    public Square() {
        // 初始化顶点字节缓冲区,用于存放形状的坐标
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (每个浮点数占用4个字节)
                squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);

        // 初始化字节缓冲区,用于存放绘制列表
        ByteBuffer dlb = ByteBuffer.allocateDirect(
                // (每个短整型占用2个字节
                drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);
    }
}

       这个例子展示了如何使用OpenGL创建更为复杂的形状。一般来说,都是通过绘制三角形对象集合的方式来达到。在下一节中,你将了解如何在屏幕上画出这些形状。

posted @ 2013-07-03 18:32  Innosight  阅读(452)  评论(0编辑  收藏  举报