定義形狀
會定義在OpenGLES view上所繪製的形狀,是你創建高端圖形應用傑作的第一步。如果你不懂OpenGLES定義圖形對象的一些基本知識,使用OpenGLES可能有一點棘手。
本文解釋OpenGLES相對於Android設備屏幕的座標系統、定義一個形狀的基礎知識、形狀的外觀、以及如何定義三角形和正方形。
定義一個三角形
OpenGLEs允許你使用坐本在三個維度上定義繪製對象。所以,在你可以繪製一個三角形之前,你必須定義它的座標。在OpenGL中,典型的方式是爲座標定義一個浮點類型的頂點數組。爲了最高效,你應把這些座標都寫進一個ByteBuffer
,它會被傳到OpenGLES圖形管線以進行處理。
class Triangle { private FloatBuffer vertexBuffer; // 數組中每個頂點的座標數 static final int COORDS_PER_VERTEX = 3; static float triangleCoords[] = { // 按逆時針方向順序: 0.0f, 0.622008459f, 0.0f, // top -0.5f, -0.311004243f, 0.0f, // bottom left 0.5f, -0.311004243f, 0.0f // bottom right }; // 設置顏色,分別爲red, green, blue 和alpha (opacity) float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; public Triangle() { // 爲存放形狀的座標,初始化頂點字節緩衝 ByteBuffer bb = ByteBuffer.allocateDirect( // (座標數 * 4)float佔四字節 triangleCoords.length * 4); // 設用設備的本點字節序 bb.order(ByteOrder.nativeOrder()); // 從ByteBuffer創建一個浮點緩衝 vertexBuffer = bb.asFloatBuffer(); // 把座標們加入FloatBuffer中 vertexBuffer.put(triangleCoords); // 設置buffer,從第一個座標開始讀 vertexBuffer.position(0); } }
缺省情況下,OpenGLES假定[0,0,0](X,Y,Z)是GLSurfaceView
幀的中心,[1,1,0]是右上角,[-1,-1,0]是左下角。
注意此形狀的座標是按逆時針方向定義的。繪製順序很重要,因爲它定義了哪面是形狀的正面,哪面是反面,使用OpenGLES的cullface特性,你可以只畫正面而不畫反面。
定義一個正方形
在OpenGL中定義正方形是十分容易的,有很多方法能做的,但是典型的做法是使用兩個三角形:
圖1.使用兩個三角形畫一個正方形
你要爲兩個三角形都按逆時針方向定義頂點們,並且將這些座標值們放入一個ByteBuffer
中。爲了避免分別爲兩個三角形定義兩個座標數組,我們使用一個繪製列表來告訴OpenGLES圖形管線如果畫這些頂點們。下面就是這個形狀的代碼:
class Square { private FloatBuffer vertexBuffer; private ShortBuffer drawListBuffer; // 每個頂點的座標數 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 }; // 頂點的繪製順序 public Square() { // initialize vertex byte buffer for shape coordinates 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)short是2字節 drawOrder.length * 2); dlb.order(ByteOrder.nativeOrder()); drawListBuffer = dlb.asShortBuffer(); drawListBuffer.put(drawOrder); drawListBuffer.position(0); } }
本例讓你見識了用OpenGL如何創建更復雜的形狀。通常,你都是使用一羣小三(三角形)來繪製對象。下一章,你將學會如何將這些形狀畫到屏幕上。