(欢迎大家加入android技术交流QQ群:209796692)


定义形状

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

本文解释OpenGLES相对于Android设备屏幕的坐标系统、定义一个形状的基础知识、形状的外观、以及如何定义三角形和正方形。

定义一个三角形


OpenGLEs允许你使用坐本在三个维度上定义绘制对象。所以,在你可以绘制一个三角形之前,你必须定义它的坐标。在OpenGL中,典型的方式是为坐标定义一个浮点类型的顶点数组。为了最高效,你应把这些坐标都写进一个ByteBuffer,它会被传到OpenGLES图形管线以进行处理。

class Triangle {

    private FloatBuffer vertexBuffer;

    // 数组中每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = { // 按逆时针方向顺序:
         0.0f, 0.622008459f, 0.0f, // top
        -0.5f, -0.311004243f, 0.0f, // bottom left
         0.5f, -0.311004243f, 0.0f // bottom right
    };

    // 设置颜色,分别为red, green, blue alpha (opacity)
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public Triangle() {
        // 存放形状的坐标,初始化顶点字节缓冲
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (坐标数 * 4)float占四字节
                triangleCoords.length * 4);
        // 设用设备的本点字节序
        bb.order(ByteOrder.nativeOrder());

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

缺省情况下,OpenGLES 假定[0,0,0](X,Y,Z) GLSurfaceView 帧的中心,[1,1,0]是右上角,[-1,-1,0]是左下角。

注意此形状的坐标是按逆时针方向定义的。绘制顺序很重要,因为它定义了哪面是形状的正面,哪面是反面,使用OpenGLES cullface特性,你可以只画正面而不画反面。

定义一个正方形


OpenGL中定义正方形是十分容易的,有很多方法能做的,但是典型的做法是使用两个三角形:


1.使用两个三角形画一个正方形

你要为两个三角形都按逆时针方向定义顶点们,并且将这些坐标值们放入一个ByteBuffer中。为了避免分别为两个三角形定义两个坐标数组,我们使用一个绘制列表来告诉OpenGLES图形管线如果画这些顶点们。下面就是这个形状的代码:

class Square {

    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;

    // 每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left
                                    -0.5f, -0.5f, 0.0f, // bottom left
                                     0.5f, -0.5f, 0.0f, // bottom right
                                     0.5f, 0.5f, 0.0f }; // top right

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

    public Square() {
        // initialize vertex byte buffer for shape coordinates
        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)short2字节
                drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);
    }
}

本例让你见识了用OpenGL如何创建更复杂的形状。通常,你都是使用一群小三(三角形)来绘制对象。下一章,你将学会如何将这些形状画到屏幕上。

上一讲

下一讲


Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐