使用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创建更为复杂的形状。一般来说,都是通过绘制三角形对象集合的方式来达到。在下一节中,你将了解如何在屏幕上画出这些形状。