Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android OpenGL入門示例:繪制三角形和正方形 (附完整源碼)

Android OpenGL入門示例:繪制三角形和正方形 (附完整源碼)

編輯:關於Android編程

Android上對OpenGl的支持是無縫的,所以才有眾多3D效果如此逼真的游戲,在Camera的一些流程中也有用到GLSurfaceView的情況。本文記錄OpenGL在Android上的入門級示例,繪制一個三角形和正方形。盡管功能簡單,可是我搗騰了好幾個晚上,大量網上文章上的代碼都有點問題,不是繪制不出來就是掛了。

第一個文件:MainActivity.Java

  1. packagecom.example.learnopengl1;
  2.  
  3. importandroid.opengl.GLSurfaceView;
  4. importandroid.os.Bundle;
  5. importandroid.app.Activity;
  6. importandroid.view.Menu;
  7.  
  8. publicclassMainActivityextendsActivity{
  9.  
  10. @Override
  11. protectedvoidonCreate(BundlesavedInstanceState){
  12. super.onCreate(savedInstanceState);
  13. GLSurfaceViewglSurfaceView=newGLSurfaceView(this);
  14. glSurfaceView.setRenderer(newOpenGLRender());
  15. setContentView(glSurfaceView);
  16. //setContentView(R.layout.activity_main);
  17.  
  18. }
  19.  
  20. @Override
  21. publicbooleanonCreateOptionsMenu(Menumenu){
  22. //Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
  23. getMenuInflater().inflate(R.menu.main,menu);
  24. returntrue;
  25. }
  26.  
  27. }
  28.  
第二個文件:BufferUtil.java 負責將數組轉成buffer
  1. packagecom.example.learnopengl1;
  2.  
  3. importjava.nio.ByteBuffer;
  4. importjava.nio.ByteOrder;
  5. importjava.nio.FloatBuffer;
  6. importjava.nio.IntBuffer;
  7.  
  8. publicclassBufferUtil{
  9. publicstaticFloatBuffermBuffer;
  10. publicstaticFloatBufferfloatToBuffer(float[]a){
  11. //先初始化buffer,數組的長度*4,因為一個float占4個字節
  12. ByteBuffermbb=ByteBuffer.allocateDirect(a.length*4);
  13. //數組排序用nativeOrder
  14. mbb.order(ByteOrder.nativeOrder());
  15. mBuffer=mbb.asFloatBuffer();
  16. mBuffer.put(a);
  17. mBuffer.position(0);
  18. returnmBuffer;
  19. }
  20.  
  21. publicstaticIntBufferintToBuffer(int[]a){
  22.  
  23. IntBufferintBuffer;
  24. //先初始化buffer,數組的長度*4,因為一個float占4個字節
  25. ByteBuffermbb=ByteBuffer.allocateDirect(a.length*4);
  26. //數組排序用nativeOrder
  27. mbb.order(ByteOrder.nativeOrder());
  28. intBuffer=mbb.asIntBuffer();
  29. intBuffer.put(a);
  30. intBuffer.position(0);
  31. returnintBuffer;
  32. }
  33. }
第三個文件:OpenGLRender.java 這是最為核心的,負責給配套的GLSurfaceView繪制東西
  1. packagecom.example.learnopengl1;
  2.  
  3. importjava.nio.FloatBuffer;
  4. importjavax.microedition.khronos.egl.EGLConfig;
  5. importjavax.microedition.khronos.opengles.GL10;
  6. importandroid.opengl.GLSurfaceView.Renderer;
  7.  
  8. publicclassOpenGLRenderimplementsRenderer{
  9.  
  10. privatefloat[]mTriangleArray={
  11. 0f,1f,0f,
  12. -1f,-1f,0f,
  13. 1f,-1f,0f
  14. };
  15. privateFloatBuffermTriangleBuffer;
  16.  
  17.  
  18. privatefloat[]mColorArray={
  19. 1f,0f,0f,1f,//紅
  20. 0f,1f,0f,1f,//綠
  21. 0f,0f,1f,1f//藍
  22. };
  23. privateFloatBuffermColorBuffer;
  24.  
  25. //正方形的四個頂點
  26. privateFloatBufferquateBuffer;
  27. privatefloat[]mQuateArray={
  28. -1f,-1f,0f,
  29. 1f,-1f,0f,
  30. -1f,1f,0f,
  31. 1f,1f,0f,
  32. };
  33.  
  34. @Override
  35. publicvoidonDrawFrame(GL10gl){
  36. //TODOAuto-generatedmethodstub
  37. gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
  38. //使用數組作為顏色
  39. gl.glColorPointer(4,GL10.GL_FLOAT,0,mColorBuffer);
  40.  
  41. //繪制小三角形
  42. gl.glLoadIdentity();
  43. gl.glTranslatef(-1.5f,0.0f,-6.0f);
  44. gl.glVertexPointer(3,GL10.GL_FLOAT,0,mTriangleBuffer);//數組指向三角形頂點buffer
  45. gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);
  46. //gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
  47. gl.glFinish();
  48.  
  49. //繪制正方形
  50. gl.glLoadIdentity();
  51. gl.glTranslatef(1.5f,0.0f,-6.0f);
  52. //gl.glColor4f(1.0f,0.0f,0.0f,1.0f);
  53. gl.glVertexPointer(3,GL10.GL_FLOAT,0,quateBuffer);
  54. gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
  55. gl.glFinish();
  56.  
  57.  
  58. }
  59.  
  60. @Override
  61. publicvoidonSurfaceChanged(GL10gl,intw,inth){
  62. //TODOAuto-generatedmethodstub
  63. gl.glViewport(0,0,w,h);
  64.  
  65. floatratio=(float)w/h;
  66. gl.glMatrixMode(GL10.GL_PROJECTION);
  67. gl.glLoadIdentity();
  68. gl.glFrustumf(-ratio,ratio,-1,1,1,10);
  69. gl.glMatrixMode(GL10.GL_MODELVIEW);
  70. gl.glLoadIdentity();
  71. }
  72.  
  73. @Override
  74. publicvoidonSurfaceCreated(GL10gl,EGLConfigconfig){
  75. //TODOAuto-generatedmethodstub
  76. gl.glShadeModel(GL10.GL_SMOOTH);
  77. gl.glClearColor(1.0f,1.0f,1.0f,0f);
  78. gl.glClearDepthf(1.0f);
  79. gl.glEnable(GL10.GL_DEPTH_TEST);
  80. gl.glDepthFunc(GL10.GL_LEQUAL);
  81. gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);
  82. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  83. gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
  84.  
  85. mTriangleBuffer=BufferUtil.floatToBuffer(mTriangleArray);
  86. mColorBuffer=BufferUtil.floatToBuffer(mColorArray);
  87. quateBuffer=BufferUtil.floatToBuffer(mQuateArray);
  88.  
  89.  
  90. }
  91.  
  92. }
開發要點:

1、GLSurfaceView可以直接new,也可以放到布局裡,本例用的是第一種方法。

2、一個GLSurfaceView要配套一個Renderer,這個Renderer是一個接口,裡面有三個函數。這點跟Surfaceview很像。尤其是其中的onDrawFrame()可以類比為Android裡View的onDraw()函數。

3、繪制的主題在onDrawFrame()函數裡,使用以下代碼繪制三角形:

//繪制小三角形
gl.glLoadIdentity();
gl.glTranslatef(-1.5f, 0.0f, -6.0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mTriangleBuffer);//數組指向三角形頂點buffer
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
// gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glFinish();

需要注意的是,在一些教程上寫著繪制完後要gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 清除所設的頂點,這是個錯誤!一旦調用此句,則什麼畫不出來了!!!

然後再繪制正方形:

//繪制正方形
gl.glLoadIdentity();
gl.glTranslatef(1.5f, 0.0f, -6.0f);
// gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, quateBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glFinish();

注意繪制三角形之前已經加載了Color:gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);

如果在繪制完後調用gl.glDisableClientState(GL10.GL_COLOR_ARRAY);的話可以看到三角形一閃而過,正方形都看不到了。這塊也是個誤解!如果後面通過gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);再次指定顏色,可以看到會以此顏色繪制三角形和正方形。 總而言之,這個onDrawFrame()和View的onDraw()很像,在onDraw裡不給paint設顏色,就畫。或者畫完後,又給顏色設成透明了,結果肯定也是啥都看不到。不明白為啥這麼多教程上在繪制完小三角形後非要帶:

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

這兩句bug!!!

關於代碼本身涉及的流程就不解釋了,參考鏈接裡說的很清楚。

4、如果正方形四個頂點坐標順序更換後,畫出來的將不是正方形。

效果圖如下所示:

\

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved