最近在总结Android OpenGL ES的开发学习过程。本章为总结第二章。主要就两大重要内容聊起。
一、OpenGL ES中的基本几何图形。
想要在OpenGL ES中画出复杂、炫酷的图形出来(比如游戏中的场景),必须掌握OpenGL ES中基本几何图形的绘制。本章使用的是GL10。
1. GL10.GL_POINTS:散点
2. GL10.GL_LINES:无关联的线段
3. GL10.GL_LINE_STRIP:连续但不封闭线段
4. GL10.GL_LINE_LOOP:连续封闭线段
5. GL10.GL_TRIANGLES:无关联三角形
6. GL10.GL_TRIANGLE_STRIP:关联三角形(说明一下,设P0P1P2P3P4P5为顶点,此时将绘制△P0P1P2、△P1P2P3、△P2P3P4、△P3P4P5四个三角形)
7. GL10.GL_TRIANGLE_FAN:共顶点三角形(说明一下,设P0P1P2P3P4P5为顶点,此时将绘制△P0P1P2、△P0P2P3、△P0P3P4、△P0P4P5四个三角形)
GL10只支持这集中基本几何图形,其他复杂的图形都是有这些基本图形合成的!!!
二、 OpenGL ES中的基本数据
要画图先要告诉设备怎么画,那么就要有图形的数据(物体上的点的坐标或者点的坐标的规律,是不是很拗口,这么说吧,就是要绘制的物体的表面的数学模型)
1. Vertex(顶点)
一个实际场景,比如有一盆仙人球(图片自行脑补)。仙人球的表面(一个粗略的球面,部分地方有点异型),球面的绘制要使用多个三角形来绘制(越多越好,当三角形的个数足够多时, 特么的,这个我打不出来,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.
详情可参考:http://www.apkbus.com/thread-50879-1-1.html
另外关于Java GC机制可以参看我的博客:JVM中内存划分和GC机制
————————不怎么华丽的分割线———————-
下一章:Android OpenGL ES 开发教程(三)