在OpenGL中,所有的东西的结构都是从一个顶点开始的。
所谓顶点,就是一个几何图形的拐点。在介绍顶点之前,我们首先介绍下OpenGL坐标。
如果有会Android开发的朋友,一定会默认为从屏幕的左上角开始,水平往右是x轴,竖直向下是y轴。
但是在OpenGL中是不同的,OpenGL是从显示视窗的正中心是中心,也就是 ( 0 , 0 ) (0, 0) (0,0),而屏幕最左边的x轴坐标是-1,屏幕最右边的x轴坐标是1,屏幕最上面的y轴坐标是1,屏幕最下面的y轴坐标是-1,也就是下面这幅图:
在OpenGL中定义顶点有点特殊,我们第一反应都是直接拿数组将顶端存起来就行了,但是在OpenGL中,你除了要将顶点的坐标用数组存起来以外,还得定义一个常量,用来标记一个顶点有两个分量:
private static final int POSITION_COMPONENT_COUNT = 2;
float[] tableVerticesWithTriangles = {
// Triangle 1
-0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
// Triangle 2
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
// Line 1
-0.5f, 0f,
0.5f, 0f,
// Mallets
0f, -0.25f,
0f, 0.25f
};
我们采用浮点数的顺序列表定义顶点数据,这个数组通常被成为顶点属性。
在OpenGL中,只能绘制点、直线和三角形,这三个也被称为图元。
也就意味着,其它所有的图形都得通过这三个基本图元来实现。
如果我们需要绘制一个点,那么一个坐标就可以了,但是如果我们需要绘制一条直线,就需要两个坐标,如果绘制一个三角形,就需要三个坐标。
那么我们就以绘制一个正方形举例:
float[] squareVerticesWithTriangles = {
-0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
0.5f, -0.5f
};
如果我要在这个正方形中间加一个横线的话,那么就直接在上面的数组里面去加,到时候要将顶点着色器加载到图形中的时候再去处理:
float[] squareVerticesWithTriangles = {
// Square
-0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
0.5f, -0.5f,
// Line
-0.5f, 0,
0.5f, 0
};
在上面,我们已经完成了顶点的定义,但是现在OpenGL尚还不能读取他们。其原因是这些代码的运行环境与OpenGL运行环境使用了不一样的语言。
当我们运行Java语言的时候,并不是直接运行在硬件上的,而是运行在JVM(纯Java)或者Dalvik(Android)虚拟机上的,并且运行在这些虚拟机上的时候,并不能直接访问本地环境;其次,虚拟机还采用的垃圾回收机制,当检测到变量、对象不再被使用时,就自动释放掉这些内存。
但是本地环境不能这样,因为他是直接运行在硬件上的,他不希望内存会被移来移去或者自动释放。
所以我们就需要一个方案,让Android程序与OpenGL进行通信。
其实Android代码与硬件通信有两种方法:
我们这块主要是通过第二种方法。
Java中有一种特殊的集合,可以分配本地的内存块,并将Java的数据复制到本地内存。代码如下:
// 因为Java中国一个Float型数据占4个字节
private static final int BYTES_PER_FLOAT = 4;
// 声明一个字节缓冲区
private final FloatBuffer vertexData;
vertexData = ByteBuffer
// 分配一块本地内存,所以是数组长度 * 类型所占字节
.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
// 按照本地字节序组织内容
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 将数据存入
.put(tableVerticesWithTriangles);