在Android應用中使用OpenGL


Android為OpenGL  ES支持提供了GLSurfaceView組件,這個組件用於顯示3D圖形。GLSurfaceView本身並不提供繪制3D圖形的功能,而是由GLSurfaceView.Renderer來完成了SurfaceView中3D圖形的繪制。

歸納起來,在Android中使用OpenGL  ES需要三個步驟:

1、創建GLSurfaceView組件,使用Activity來顯示GLSurfaceView組件。

2、為GLSurfaceView組件創建GLSurfaceView.Renderer實例,實現GLSurfaceView.Renderer類時需要實現該接口里的三個方法:

  abstract  void  onDrawFrame(GL10  gl):Renderer對象調用該方法繪制GLSurfaceView的當前幀。

  abstract  void  onSurfaceChanged(GL10  gl , int  width  ,int  height):當GLSurfaceView的大小改變時回調該方法。

  abstract  void  onSurfaceCreated(GL10  gl  ,  EGLConfig  config):當GLSurfaceView被創建時回調該方法。

3、調用GLSurfaceView組件的setRenderer()方法指定Renderer對象,該Renderer對象將會完成GLSurfaceView里3D圖像的繪制。

從上面的介紹不難看出,實際上繪制3D圖形的難點不是如何使用GLSurfaceView組件,而是如何實現Renderer類。實現Renderer類時需要實現三個方法,這三個方法都有一個GL10形參,它就代表了GLOpen  ES的“繪制畫筆”,我們可以把它想象成Swing  2D繪圖中的Graphics,也可以想象成Android  2D繪圖中的Canvas組件-----當我們希望Renderer繪制3D圖形時,實際上是調用GL10的方法來進行繪制的。

當SurfaceView被創建時,系統會回調Renderer對象的onSurfaceCreated()方法,該方法將可以對OpenGL  ES執行一些無須任何改變的初始化,例如:

@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);
}

GL10就是OpenGL  ES的繪圖接口,但實際上他也是GL11的實例,可通過(gl  Instansof  GL11)判斷它是否為GL11接口的實例。

glDisable(int  cap):該方法用於禁用OpenGL  ES某個方面的特性,上例中代碼用於關閉抗抖性,這樣可以提高性能。

glHint(int  target  , int mode):該方法用於對OpenGL  ES某方法進行修正。

clearColor(float  red  ,  float green  ,  float  blue  , float  alpha):該方法設置OpenGL  ES“清屏”所用的顏色,四個參數分別設置紅、綠、藍、透明度值;0為最小值,1為最大值。例如設置gl.glClearColor(0 ,  0 , 0 , 0):就是用黑色“清屏”。

glShadeMode(int  mode):該方法用於設置OpenGL  ES的陰影模式,此處設為陰影平滑模式。

glEnable(int  cap):該方法與glDisable(int  cap)方法相對,用於啟用OpenGL  ES某方面的特性,此處用於啟動OpenGL  ES的深度測試,所謂“深度測試”,就是讓OpenGL  ES負責跟蹤每個物體在Z軸上的深度,這樣就可避免后面的物體遮擋前面的物體。

當SurfaceView組件的大小發生改變時,系統會回調Renderer對象的onSurfaceChanged()方法,因此該方法通常用於初始化3D場景。例如如下初始化代碼:

@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);
}

上面的方法中用到了GL10的一些初始化方法,此處做簡要說明:

glViewport(int  x , int  y  ,  int  width ,  int  height):設置3D視窗的位置與大小。其中前兩個參數指定該視窗的位置,后兩個參數指定該視窗的寬、高。

glMatrixMode(int  mode):設置視圖的矩陣模型。通常可接受GL10.GL_PROJECTION、GL10.GL_MODEVIEW兩個常量值。

  當調用glMatrixMode(GL10.GL_PROJECTION):代碼后,指定將屏幕視為透視圖(要想看到逼真的三維物體,這是必要的),這意味着越遠的東西看起來越小;當調用glMatrixMode(GL10.GL_MODEVIEW):代碼后,即將當前矩陣模式設為模型視圖矩陣,這意味着任何新的變換都會影響該矩陣中的所有物體。

glLoadIdentity():相當於reset()方法,用於初始化單位矩陣。

glFrustumf(float  left  , float  right , float  bottom , float  top , float  zNear  ,  float  zFar):用於設置透視投影的空間大小。前路兩個參數用於設置X軸上的最小坐標值、最大坐標值;中間兩個參數用於設置Y軸上的最小坐標值、最大坐標值;后面兩個參數用於設置Z軸上所能繪制的場景的深度的最小值、最大值。

注:三維坐標系統與二維坐標系統並不相同,而二維坐標系統上的坐標值通常就直接使用系統的像素數量;但三維坐標系統的坐標值則取決於glFrustumf()方法的設置。

GLSurfaceView上的所有3D圖形都是有Renderer的onDrawFrame(GL10  gl)方法繪制出來的,重寫該方法時就要把所有3D圖形都繪制出來,該方法通常以如下形式開始:

 

@Override
public void onDrawFrame(GL10 gl) {
  // 清除屏幕緩存和深度緩存
  gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM