原文:https://developer.android.com/training/graphics/opengl/shapes.html
Being able to define shapes to be drawn in the context of an OpenGL ES view is the first step in creating your high-end graphics masterpiece. Drawing with OpenGL ES can be a little tricky without knowing a few basic things about how OpenGL ES expects you to define graphic objects.
绘制复杂的图形的第一步是定义一些基本的形状,在OpenGL ES view的context上画出来。使用OpenGL ES画图可能会有点邪门😢,如果你不清楚一些绘制的基础知识。
This lesson explains the OpenGL ES coordinate system relative to an Android device screen, the basics of defining a shape, shape faces, as well as defining a triangle and a square.
这一课讲解相于Android屏幕而言OpenGL ES的坐标体系。定义基本形状的基础,以及如何定义一下三角形和正方形。
Define a Triangle
定义一个三角形
OpenGL ES allows you to define drawn objects using coordinates in three-dimensional space. So, before you can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do this is to define a vertex array of floating point numbers for the coordinates. For maximum efficiency, you write these coordinates into a ByteBuffer, that is passed into the OpenGL ES graphics pipeline for processing.
OpenGL ES使用三维空间的坐标来定义需要绘制的物体。所以,在绘制一个三角形之前,你必须定义它的坐标。在使用OpenGL的时候,定义坐标最典型的方式是定义一个顶点(vertex)浮点数组。为了提高效率,需要把这些坐标写进一个ByteBuffer, 这个ByteBuffer会被传进OpenGL ES的绘图管道进行处理。🤔
public class Triangle {
private FloatBuffer vertexBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = { // in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
}
}
By default, OpenGL ES assumes a coordinate system where [0,0,0] (X,Y,Z) specifies the center of the GLSurfaceView frame, [1,1,0] is the top right corner of the frame and [-1,-1,0] is bottom left corner of the frame. For an illustration of this coordinate system, see the OpenGL ES developer guide.
默认情况下,OpenGL ES的坐标体系里,0,0,0代表了GLSurfaceView的正中央坐标,[1,1,0] 是右上角坐标,[-1,-1,0]是左下角坐标。有关这个坐标体系的插图,可以在OpenGL ES开发指导里看到。
Note that the coordinates of this shape are defined in a counterclockwise order. The drawing order is important because it defines which side is the front face of the shape, which you typically want to have drawn, and the back face, which you can choose to not draw using the OpenGL ES cull face feature. For more information about faces and culling, see the OpenGL ES developer guide.
注意,这个形状的坐标是按逆时针来定义的。绘制的顺序很重要,因为它定义了形状的正面,一般来说,你需要画的都是正面。背面可以选择不画。有关正反面的信息,你可以查看OpenGL ES开发指导。(你妹!😤)
Define a Square
Defining triangles is pretty easy in OpenGL, but what if you want to get a just a little more complex? Say, a square? There are a number of ways to do this, but a typical path to drawing such a shape in OpenGL ES is to use two triangles drawn together:
定义一个三角形简直是图样图森破,如果你想要一个更复杂的图形,比如一个正方形,傻B了吧?有很多种方法可以实现,但是典型的做法是用两个三角形拼一个正方形。😱
Again, you should define the vertices in a counterclockwise order for both triangles that represent this shape, and put the values in a ByteBuffer. In order to avoid defining the two coordinates shared by each triangle twice, use a drawing list to tell the OpenGL ES graphics pipeline how to draw these vertices. Here’s the code for this shape:
当然,在定义这两个三角形坐标的时候,你还是需要按逆时针来,然后把坐标放进ByteBuffer. 左上和右下两个坐标是两个三角形共用的,为了不重复定义,用一个drawing list告诉OpenGL ES绘图管道,怎么画这些顶点(vertice). 下面就是这个图标的代码:
public class Square {
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
// number of coordinates per vertex in this array
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 }; // order to draw vertices
public Square() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
}
}
This example gives you a peek at what it takes to create more complex shapes with OpenGL. In general, you use collections of triangles to draw objects. In the next lesson, you learn how to draw these shapes on screen.
这个例子只是让你简单见识一下怎么绘制更复杂的形状😓。一句话,用多个三角形来实现不同的形状。下一课,学习如何把这些形状画到手机屏幕上。