初學Android,OpenGL ES之繪製平面多邊形(八十)
在Android中使用OpenGL ES需三步
1.建立GLSurfaceView元件,使用Activity顯示GLSurfaceView元件
2.為GLSurfaceView建立GLSurfaceView.Renderer例項,實現Renderer類時需要實現接口裡的三個方法
void onDrawFrame(GL10 gl) Renderer物件呼叫此方法繪製GLSurfaceView的當前幀
void onSurfaceChanged(GL10 gl, int width, int height) GLSurfaceView的大小改變時回撥方法
void onSurfaceCreated(GL10 gl, EGLConfig config) GLSurfaceView建立時回撥此方法
上面的引數GL10,相當於是Android 2D繪圖中的Canvas,GL10就是繪製圖形的畫筆
繪製2D圖形的步驟基本都是呼叫GL10的方法
1.呼叫glEnableClientState(GL10.GL_VERTEX_ARRAY); 啟用頂點座標資料
2.呼叫glEnableClientState(GL10.GL_COLOR_ARRAY); 啟用頂點顏色資料
3.呼叫glVertexPointer(int size, int type, int stride, Buffer pointer); 設定位置頂點資料
引數size,指定多少個元素指定一個頂點位置,通常是3(x,y,z三軸座標),引數type表示座標資料型別,可以是整型或浮點型,
pointer是一個一維陣列,格式為(x1,y1,z1,x2,y2,z2......xN,yN,xN),按順序每三個為一組代表一個頂點的x,y,z的座標
4.呼叫glVertexPointer(int size, int type, int stride, Buffer pointer);
引數跟glVertexPointer差不多,只是pointer是4個為一組指定頂點的顏色,分別是紅,綠,藍,透明度的值
5.呼叫glDrawArrays(int mode, int first, int count) 繪製平面
第一個引數指定繪製圖形型別,第二個引數指定從哪個頂點開始繪製,第三個引數指定總共繪製的頂點數
下面是一個例子
先定義一個Renderer
public class MyRenderer implements Renderer {
float[] triangleData = new float[] { 0.1f, 0.6f, 0.0f, // 上頂點
-0.3f, 0.0f, 0.0f, // 左頂點
0.3f, 0.1f, 0.0f // 右頂點
};
int[] triangleColor = new int[] { 65535, 0, 0, 0, // 上頂點紅色
0, 65535, 0, 0, // 左頂點綠色
0, 0, 65535, 0 // 右頂點藍色
};
float[] rectData = new float[] { 0.4f, 0.4f, 0.0f, // 右上頂點
0.4f, -0.4f, 0.0f, // 右下頂點
-0.4f, 0.4f, 0.0f, // 左上頂點
-0.4f, -0.4f, 0.0f // 左下頂點
};
int[] rectColor = new int[] { 0, 65535, 0, 0, // 右上頂點綠色
0, 0, 65535, 0, // 右下頂點藍色
65535, 0, 0, 0, // 左上頂點紅色
65535, 65535, 0, 0 // 左下頂點黃色
};
// 依然是正方形的四個頂點,只是順序交換了一下
float[] rectData2 = new float[] { -0.4f, 0.4f, 0.0f, // 左上頂點
0.4f, 0.4f, 0.0f, // 右上頂點
0.4f, -0.4f, 0.0f, // 右下頂點
-0.4f, -0.4f, 0.0f // 左下頂點
};
float[] pentacle = new float[] { 0.4f, 0.4f, 0.0f, -0.2f, 0.3f, 0.0f, 0.5f,
0.0f, 0f, -0.4f, 0.0f, 0f, -0.1f, -0.3f, 0f };
FloatBuffer triangleDataBuffer;
IntBuffer triangleColorBuffer;
FloatBuffer rectDataBuffer;
IntBuffer rectColorBuffer;
FloatBuffer rectDataBuffer2;
FloatBuffer pentacleBuffer;
public MyRenderer() {
// 將頂點位置資料陣列包裝成FloatBuffer;
triangleDataBuffer = FloatBuffer.wrap(triangleData);
rectDataBuffer = FloatBuffer.wrap(rectData);
rectDataBuffer2 = FloatBuffer.wrap(rectData2);
pentacleBuffer = FloatBuffer.wrap(pentacle);
// 將頂點顏色資料陣列包裝成IntBuffer;
triangleColorBuffer = IntBuffer.wrap(triangleColor);
rectColorBuffer = IntBuffer.wrap(rectColor);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 關閉抗抖動
gl.glDisable(GL10.GL_DITHER);
// 設定系統對透視進行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(0, 0, 0, 0);
// 設定陰影平滑模式
gl.glShadeModel(GL10.GL_SMOOTH);
// 啟用深度測試
gl.glEnable(GL10.GL_DEPTH_TEST);
// 設定深度測試的型別
gl.glDepthFunc(GL10.GL_LEQUAL);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 設定3D視窗的大小及位置
gl.glViewport(0, 0, width, height);
// 將當前矩陣模式設為投影矩陣
gl.glMatrixMode(GL10.GL_PROJECTION);
// 初始化單位矩陣
gl.glLoadIdentity();
// 計算透視視窗的寬度、高度比
float ratio = (float) width / height;
// 呼叫此方法設定透視視窗的空間大小。
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}
// 繪製圖形的方法
@Override
public void onDrawFrame(GL10 gl) {
// 清除螢幕快取和深度快取
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 啟用頂點座標資料
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 啟用頂點顏色資料
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
// 設定當前矩陣堆疊為模型堆疊,
gl.glMatrixMode(GL10.GL_MODELVIEW);
// --------------------繪製第一個圖形---------------------
// 重置當前的模型檢視矩陣
gl.glLoadIdentity();
gl.glTranslatef(-0.32f, 0.35f, -1f);
// 設定頂點的位置資料
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleDataBuffer);
// 設定頂點的顏色資料
gl.glColorPointer(4, GL10.GL_FIXED, 0, triangleColorBuffer);
// 根據頂點資料繪製平面圖形
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
// --------------------繪製第二個圖形---------------------
// 重置當前的模型檢視矩陣
gl.glLoadIdentity();
gl.glTranslatef(0.6f, 0.8f, -1.5f);
// 設定頂點的位置資料
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, rectDataBuffer);
// 設定頂點的顏色資料
gl.glColorPointer(4, GL10.GL_FIXED, 0, rectColorBuffer);
// 根據頂點資料繪製平面圖形
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
// --------------------繪製第3個圖形---------------------
// 重置當前的模型檢視矩陣
gl.glLoadIdentity();
gl.glTranslatef(-0.4f, -0.5f, -1.5f);
// 設定頂點的位置資料(依然使用之前的頂點顏色)
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, rectDataBuffer2);
// 根據頂點資料繪製平面圖形
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
// --------------------繪製第4個圖形---------------------
// 重置當前的模型檢視矩陣
gl.glLoadIdentity();
gl.glTranslatef(0.4f, -0.5f, -1.5f);
// 設定使用純色填充
gl.glColor4f(1.0f, 0.2f, 0.2f, 0.0f);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
// 設定頂點的位置資料
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, pentacleBuffer);
// 根據頂點資料繪製平面圖形
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 5);
// 繪製結束
gl.glFinish();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
再到Activity中使用此Rendererpublic class Polygon extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 建立一個GLSurfaceView,用於顯示OpenGL繪製的圖形
GLSurfaceView glView = new GLSurfaceView(this);
// 建立GLSurfaceView的內容繪製器
MyRenderer myRender = new MyRenderer();
// 為GLSurfaceView設定繪製器
glView.setRenderer(myRender);
setContentView(glView);
}
}