Android OpenGL入门示例:绘制三角形和正方形 (附完整源码)

来源:互联网 发布:borderlands 2 mac 编辑:程序博客网 时间:2024/06/06 02:29

Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况。本文记录OpenGL在Android上的入门级示例,绘制一个三角形和正方形。尽管功能简单,可是我捣腾了好几个晚上,大量网上文章上的代码都有点问题,不是绘制不出来就是挂了。

第一个文件:MainActivity.Java

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package com.example.learnopengl1;  
  2.   
  3. import android.opengl.GLSurfaceView;  
  4. import android.os.Bundle;  
  5. import android.app.Activity;  
  6. import android.view.Menu;  
  7.   
  8. public class MainActivity extends Activity {  
  9.   
  10.     @Override  
  11.     protected void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         GLSurfaceView glSurfaceView = new GLSurfaceView(this);  
  14.         glSurfaceView.setRenderer(new OpenGLRender());  
  15.         setContentView(glSurfaceView);  
  16.         //setContentView(R.layout.activity_main);  
  17.       
  18.     }  
  19.   
  20.     @Override  
  21.     public boolean onCreateOptionsMenu(Menu menu) {  
  22.         // Inflate the menu; this adds items to the action bar if it is present.  
  23.         getMenuInflater().inflate(R.menu.main, menu);  
  24.         return true;  
  25.     }  
  26.   
  27. }  
  28. </span>  

第二个文件:BufferUtil.java 负责将数组转成buffer

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package com.example.learnopengl1;  
  2.   
  3. import java.nio.ByteBuffer;  
  4. import java.nio.ByteOrder;  
  5. import java.nio.FloatBuffer;  
  6. import java.nio.IntBuffer;  
  7.   
  8. public class BufferUtil {  
  9.     public static FloatBuffer mBuffer;  
  10.     public static FloatBuffer floatToBuffer(float[] a){  
  11.         //先初始化buffer,数组的长度*4,因为一个float占4个字节  
  12.         ByteBuffer mbb = 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.         return mBuffer;  
  19.     }  
  20.       
  21.     public static IntBuffer intToBuffer(int[] a){  
  22.           
  23.         IntBuffer intBuffer;  
  24.         //先初始化buffer,数组的长度*4,因为一个float占4个字节  
  25.         ByteBuffer mbb = 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.         return intBuffer;  
  32.     }  
  33. }</span>  

第三个文件:OpenGLRender.java 这是最为核心的,负责给配套的GLSurfaceView绘制东西

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package com.example.learnopengl1;  
  2.   
  3. import java.nio.FloatBuffer;  
  4. import javax.microedition.khronos.egl.EGLConfig;  
  5. import javax.microedition.khronos.opengles.GL10;  
  6. import android.opengl.GLSurfaceView.Renderer;  
  7.   
  8. public class OpenGLRender implements Renderer {  
  9.   
  10.     private float[] mTriangleArray = {  
  11.             0f,1f,0f,  
  12.             -1f,-1f,0f,  
  13.             1f,-1f,0f  
  14.     };  
  15.     private FloatBuffer mTriangleBuffer;  
  16.   
  17.   
  18.     private float[] mColorArray={  
  19.             1f,0f,0f,1f,     //红  
  20.             0f,1f,0f,1f,     //绿  
  21.             0f,0f,1f,1f      //蓝  
  22.     };  
  23.     private FloatBuffer mColorBuffer;  
  24.   
  25.     //正方形的四个顶点  
  26.     private FloatBuffer quateBuffer ;  
  27.     private float[] mQuateArray = {  
  28.             -1f, -1f, 0f,  
  29.             1f, -1f, 0f,  
  30.             -1f, 1f, 0f,  
  31.             1f, 1f, 0f,  
  32.     };  
  33.   
  34.     @Override  
  35.     public void onDrawFrame(GL10 gl) {  
  36.         // TODO Auto-generated method stub  
  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, 03);  
  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, 04);  
  55.         gl.glFinish();  
  56.   
  57.   
  58.     }  
  59.   
  60.     @Override  
  61.     public void onSurfaceChanged(GL10 gl, int w, int h) {  
  62.         // TODO Auto-generated method stub  
  63.         gl.glViewport(00, w, h);  
  64.   
  65.         float ratio = (float) w / h;  
  66.         gl.glMatrixMode(GL10.GL_PROJECTION);  
  67.         gl.glLoadIdentity();  
  68.         gl.glFrustumf(-ratio, ratio, -11110);  
  69.         gl.glMatrixMode(GL10.GL_MODELVIEW);  
  70.         gl.glLoadIdentity();  
  71.     }  
  72.   
  73.     @Override  
  74.     public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
  75.         // TODO Auto-generated method stub  
  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. }  
  93. </span>  

开发要点:

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、如果正方形四个顶点坐标顺序更换后,画出来的将不是正方形。

源码链接:http://download.csdn.net/detail/yanzi1225627/7484793

参考: 链接1 链接2

效果图如下所示:

0 0
原创粉丝点击