最近在总结Android OpenGL ES的开发学习过程。本章为总结第二章。主要就两大重要内容聊起。

一、OpenGL ES中的基本几何图形。

想要在OpenGL ES中画出复杂、炫酷的图形出来(比如游戏中的场景),必须掌握OpenGL ES中基本几何图形的绘制。本章使用的是GL10。

1. GL10.GL_POINTS:散点

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_android


2. GL10.GL_LINES:无关联的线段

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_opengl es_02


3. GL10.GL_LINE_STRIP:连续但不封闭线段

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_opengl es_03


4. GL10.GL_LINE_LOOP:连续封闭线段

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_android_04


5. GL10.GL_TRIANGLES:无关联三角形

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_opengl es_05


6. GL10.GL_TRIANGLE_STRIP:关联三角形(说明一下,设P0P1P2P3P4P5为顶点,此时将绘制△P0P1P2、△P1P2P3、△P2P3P4、△P3P4P5四个三角形)

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_java_06


7. GL10.GL_TRIANGLE_FAN:共顶点三角形(说明一下,设P0P1P2P3P4P5为顶点,此时将绘制△P0P1P2、△P0P2P3、△P0P3P4、△P0P4P5四个三角形)

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_java_07

GL10只支持这集中基本几何图形,其他复杂的图形都是有这些基本图形合成的!!!

二、 OpenGL ES中的基本数据

要画图先要告诉设备怎么画,那么就要有图形的数据(物体上的点的坐标或者点的坐标的规律,是不是很拗口,这么说吧,就是要绘制的物体的表面的数学模型)

1. Vertex(顶点)

一个实际场景,比如有一盆仙人球(图片自行脑补)。仙人球的表面(一个粗略的球面,部分地方有点异型),球面的绘制要使用多个三角形来绘制(越多越好,当三角形的个数足够多时,

Android Studio 安装 OpenGL ES 和 EGL 依赖 android opengles2.0教程_图形_08

特么的,这个我打不出来,x表示三角形的个数,或者点的个数。x趋向于无穷大,就可以绘制出一个完美的球出来)

绘制散点(顶点)需要给出点的坐标,并且数据类型必须转化为指定的类型(java.nio.Buffer),下面是一个例子:

private float vertices[] = {
        -1.0f, 1.0f, 0.0f,
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        1.0f, 1.0f, 0.0f
    }
    /** {@link ByteBuffer#allocateDirect(int size)}
     * 因为在OpenGL ES 中要求的数据类型是Buffer类型。
     * 因此要对float进行转化,即将float数组转换成FloatBuffer
     * allocateDirect中设置的是Buffer的大小:
     * 复习下Java中各基本数据类型之间的关系(你就会明白为什么要乘以4):
     * byte       8bit       1字节
     * char       16bit      2字节
     * short      16bit      2字节
     * int        32bit      4字节
     * long       64bit      8字节
     * float      32bit      4字节
     * double     64bit      8字节
     * 
     * 可以清晰的看出 1 float = 4 byte
     */
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteBuffer.nativeOrder());
    FloatBuffer vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

2.Edge(边) 无需直接创建,在绘制面(三角形)时,会自动绘制三条边。
3.Face(面) 在定义面时,顶点的顺序是有要求的:
因为在绘制面时,顶点的顺序不同,绘制的面的方向也是不同的:
1) 顶点的顺序如果是逆时针排布,那么你看到的面就是此面的正面。
2) 顶点的顺序如果是顺时针排布,那么你看到的面是此面的背面。
*一般来说绘制面为了提升性能,只绘制面的正面,而不绘制面的背面:

// 1.绘制正面
    gl.glFrontFace(GL10.GL_CCW);
    // 2.打开“忽略”设置
    gl.glEnable(GL10.GL_CULL_FACE);
    // 3.指定忽略的对象
    gl.glCullFace(GL10.GL_BACK);

4.Buffer
为了提升绘图性能,通常将vertex、color存储在Buffer中。
Buffer这个类放在了Java.nio包中,nio表示的是new io的意思,是一个新的IO流包,流就是将文件等数据看作是byte数组。这种方法一般无法指定字节顺序(不同的计算机系统Byte order 可能不同),操作如“在文件偏移10个字节出读取一个四字节Little-endian整数“在使用Stream方式读取文件时就不十分方便。此外,Stream 方法是按一个字节一个字节方式处理的,读写性能上不是很好。
java.nio 解决了上述java.io 包的这些局限,java.io 包包含了Buffer,Channel, Charset 等,但OpenGL ES 只用到Buffer,Buffer具有以下特点:
1). 允许以内存缓冲区(buffer)的方式来管理一个Buffer 数组,可以整块整块的读写内存区域,并可以指定Byte order.(大头或是小头)。
2). 提供了在指定位置读写各种基本数据类型的简便方法如 putInt ,putLong等。
3). 可以充分利用JVM提供的各种优化方法以达到和使用Native Code类型的读写性能。
4). 可以直接从OS的内存分配空间,这部分空间可以不受Java 的Garbage collector控制。称为Direct buffer.