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

第一个文件:MainActivity.java

package com.example.learnopengl1;import android.opengl.GLSurfaceView;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);GLSurfaceView glSurfaceView = new GLSurfaceView(this);glSurfaceView.setRenderer(new OpenGLRender());setContentView(glSurfaceView);//setContentView(R.layout.activity_main);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

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

package com.example.learnopengl1;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import java.nio.IntBuffer;public class BufferUtil {public static FloatBuffer mBuffer;public static FloatBuffer floatToBuffer(float[] a){//先初始化buffer,数组的长度*4,因为一个float占4个字节ByteBuffer mbb = ByteBuffer.allocateDirect(a.length*4);//数组排序用nativeOrdermbb.order(ByteOrder.nativeOrder());mBuffer = mbb.asFloatBuffer();mBuffer.put(a);mBuffer.position(0);return mBuffer;}public static IntBuffer intToBuffer(int[] a){IntBuffer intBuffer;//先初始化buffer,数组的长度*4,因为一个float占4个字节ByteBuffer mbb = ByteBuffer.allocateDirect(a.length*4);//数组排序用nativeOrdermbb.order(ByteOrder.nativeOrder());intBuffer = mbb.asIntBuffer();intBuffer.put(a);intBuffer.position(0);return intBuffer;}}

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

package com.example.learnopengl1;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLSurfaceView.Renderer;public class OpenGLRender implements Renderer {private float[] mTriangleArray = {0f,1f,0f,-1f,-1f,0f,1f,-1f,0f};private FloatBuffer mTriangleBuffer;private float[] mColorArray={1f,0f,0f,1f,     //红0f,1f,0f,1f,     //绿0f,0f,1f,1f      //蓝};private FloatBuffer mColorBuffer;//正方形的四个顶点private FloatBuffer quateBuffer ;private float[] mQuateArray = {-1f, -1f, 0f,1f, -1f, 0f,-1f, 1f, 0f,1f, 1f, 0f,};@Overridepublic void onDrawFrame(GL10 gl) {// TODO Auto-generated method stubgl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);//使用数组作为颜色gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);//绘制小三角形gl.glLoadIdentity();gl.glTranslatef(-1.5f, 0.0f, -6.0f);gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mTriangleBuffer);//数组指向三角形顶点buffergl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);//gl.glDisableClientState(GL10.GL_COLOR_ARRAY);gl.glFinish();//绘制正方形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();}@Overridepublic void onSurfaceChanged(GL10 gl, int w, int h) {// TODO Auto-generated method stubgl.glViewport(0, 0, w, h);float ratio = (float) w / h;gl.glMatrixMode(GL10.GL_PROJECTION);gl.glLoadIdentity();gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glLoadIdentity();}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// TODO Auto-generated method stubgl.glShadeModel(GL10.GL_SMOOTH);gl.glClearColor(1.0f, 1.0f, 1.0f, 0f);gl.glClearDepthf(1.0f);gl.glEnable(GL10.GL_DEPTH_TEST);gl.glDepthFunc(GL10.GL_LEQUAL);gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glEnableClientState(GL10.GL_COLOR_ARRAY);mTriangleBuffer = BufferUtil.floatToBuffer(mTriangleArray);mColorBuffer = BufferUtil.floatToBuffer(mColorArray);quateBuffer = BufferUtil.floatToBuffer(mQuateArray);}}

开发要点:

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

效果图如下所示:

Android OpenGL入门示例:绘制三角形和正方形 (附完整源码)_第1张图片


更多相关文章

  1. Android 3D 旋转的三角形(一)
  2. Android OpenGL ES 画正方形
  3. Android RecyclerView 网格显示正方形
  4. Android中ArrayList动态数组用法
  5. 【Java】java和android网络编程 - 对byte数组压缩和解压缩(zip,g
  6. android之xml定义数组
  7. android okgo post传数组
  8. C# android base-64 字符数组的无效长度
  9. OpenGL ES 画正方形

随机推荐

  1. SpannableString的使用方法
  2. 重磅出击,Google Android经典资料!
  3. Android的加速度传感器模拟摇一摇的效果-
  4. Android核心模块
  5. Android之基本样式和布局
  6. android gradle 自动动态构建多平台的包
  7. 二.Android项目结构
  8. Configuration类简介
  9. APK安装路径移动至外部存储设备
  10. Android Binder机制 - defaultServiceMan