編寫:jdneo - 原文:http://developer.android.com/training/graphics/opengl/shapes.html
在一個(gè)OpenGL ES View的上下文(Context)中定義形狀,是創(chuàng)建你的杰作所需要的第一步。在了解關(guān)于OpenGL ES如何定義圖形對(duì)象的基本知識(shí)之前,通過OpenGL ES 繪圖可能會(huì)有些困難。
這節(jié)課將講解OpenGL ES相對(duì)于Android設(shè)備屏幕的坐標(biāo)系,定義形狀和形狀表面的基本知識(shí),如定義一個(gè)三角形和一個(gè)矩形。
OpenGL ES允許我們使用三維空間的坐標(biāo)來定義繪畫對(duì)象。所以在我們能畫三角形之前,必須先定義它的坐標(biāo)。在OpenGL 中,典型的辦法是為坐標(biāo)定義一個(gè)浮點(diǎn)型的頂點(diǎn)數(shù)組。為了高效起見,我們可以將坐標(biāo)寫入一個(gè)ByteBuffer,它將會(huì)傳入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);
}
}
默認(rèn)情況下,OpenGL ES會(huì)假定一個(gè)坐標(biāo)系,在這個(gè)坐標(biāo)系中,[0, 0, 0](分別對(duì)應(yīng)X軸坐標(biāo), Y軸坐標(biāo), Z軸坐標(biāo))對(duì)應(yīng)的是GLSurfaceView的中心。[1, 1, 0]對(duì)應(yīng)的是右上角,[-1, -1, 0]對(duì)應(yīng)的則是左下角。如果想要看此坐標(biāo)系的插圖說明,可以閱讀OpenGL ES開發(fā)手冊(cè)。
注意到這個(gè)形狀的坐標(biāo)是以逆時(shí)針順序定義的。繪制的順序非常關(guān)鍵,因?yàn)樗x了哪一面是形狀的正面(希望繪制的一面),以及背面(使用OpenGL ES的Cull Face功能可以讓背面不要繪制)。更多關(guān)于該方面的信息,可以閱讀OpenGL ES開發(fā)手冊(cè)。
在OpenGL中定義三角形非常簡單,那么你是否想要來點(diǎn)更復(fù)雜的呢?比如,定義一個(gè)矩形?有很多方法可以用來定義矩形,不過在OpenGL ES中最典型的辦法是使用兩個(gè)三角形拼接在一起:
http://wiki.jikexueyuan.com/project/android-training-geek/images/ccw-square.png" alt="ccw-square" title="使用兩個(gè)三角形畫一個(gè)矩形" />
再一次地,我們需要逆時(shí)針地為三角形頂點(diǎn)定義坐標(biāo)來表現(xiàn)這個(gè)圖形,并將值放入一個(gè)ByteBuffer中。為了避免由兩個(gè)三角形重合的那條邊的頂點(diǎn)被重復(fù)定義,可以使用一個(gè)繪制列表來告訴OpenGL ES圖形處理流程應(yīng)該如何畫這些頂點(diǎn)。下面是代碼樣例:
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);
}
}
該樣例可以看作是一個(gè)如何使用OpenGL創(chuàng)建復(fù)雜圖形的啟發(fā),通常來說,我們需要使用三角形的集合來繪制對(duì)象。在下一節(jié)課中,我們將學(xué)習(xí)如何在屏幕上畫這些形狀。