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

第一个文件:MainActivity.java

package com.example.opentest;

import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setRenderer(new OpenGLRender());
setContentView(glSurfaceView);
//setContentView(R.layout.activity_main); } @Override
public 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.opentest;

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*);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
mBuffer = mbb.asFloatBuffer();
mBuffer.put(a);
mBuffer.position();
return mBuffer;
} public static IntBuffer intToBuffer(int[] a){ IntBuffer intBuffer;
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length*);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
intBuffer = mbb.asIntBuffer();
intBuffer.put(a);
intBuffer.position();
return intBuffer;
}
}

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

package com.example.opentest;

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,
}; @Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
//使用数组作为颜色
gl.glColorPointer(, GL10.GL_FLOAT, , mColorBuffer); //绘制小三角形
gl.glLoadIdentity();
gl.glTranslatef(-1.5f, 0.0f, -6.0f);
gl.glVertexPointer(, GL10.GL_FLOAT, , mTriangleBuffer);//数组指向三角形顶点buffer
gl.glDrawArrays(GL10.GL_TRIANGLES, , );
// 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(, GL10.GL_FLOAT, , quateBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, , );
gl.glFinish(); } @Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
// TODO Auto-generated method stub
gl.glViewport(, , w, h); float ratio = (float) w / h;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -, , , );
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
} @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
gl.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(, GL10.GL_FLOAT, , mTriangleBuffer);//数组指向三角形顶点
buffergl.glDrawArrays(GL10.GL_TRIANGLES, , );
// 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(, GL10.GL_FLOAT, , quateBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, , );
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. Linux OpenGL 实践篇-3 绘制三角形

    本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用. 顶点数组对象 顶点数组对象负责管理一组顶点属性,顶点属性包括位置.法线.纹理坐标等. OpenGL缓存 OpenGL缓存实质上 ...

  2. iOS OpenGL ES简单绘制三角形

    OpenGL 是用于2D/3D图形编程的一套基于C语言的统一接口. windows,Linux,Unix上均可兼容. OpenGL ES 是在OpenGL嵌入式设备上的版本, android/iOS ...

  3. Android OpenGL ES(七)基本几何图形定义 .

    在前面Android OpenGL ES(六):创建实例应用OpenGLDemos程序框架 我们创建了示例程序的基本框架,并提供了一个“Hello World”示例,将屏幕显示为红色. 本例介绍Ope ...

  4. Android OpenGL ES(十)绘制三角形Triangle .

    三角形为OpenGL ES支持的面,同样创建一个DrawTriangle Activity,定义6个顶点使用三种不同模式来绘制三角形: float vertexArray[] = { -0.8f, - ...

  5. Android OpenGL ES 开发教程 从入门到精通

    感谢,摘自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ...

  6. Android OpenGL ES(八)绘制点Point ..

    上一篇介绍了OpenGL ES能够绘制的几种基本几何图形:点,线,三角形.将分别介绍这几种基本几何图形的例子.为方便起见,暂时在同一平面上绘制这些几何图形,在后面介绍完OpenGL ES的坐标系统和坐 ...

  7. Android OpenGL ES(十一)绘制一个20面体 .

    前面介绍了OpenGL ES所有能够绘制的基本图形,点,线段和三角形.其它所有复杂的2D或3D图形都是由这些基本图形构成. 本例介绍如何使用三角形构造一个正20面体.一个正20面体,有12个顶点,20 ...

  8. android openGL ES2 一切从绘制纹理開始

    纹理.在openGL中,能够理解为载入到显卡显存中的图片.Android设备在2.2開始支持openGL ES2.0.从前都是ES1.0 和 ES1.1的版本号.简单来说,openGL ES是为了嵌入 ...

  9. Android OpenGL ES 开发:绘制图形

    OpenGL 绘制图形步骤 上一篇介绍了 OpenGL 的相关概念,今天来实际操作,使用 OpenGL 绘制出图形,对其过程有一个初步的了解. OpenGL 绘制图形主要概括成以下几个步骤: 创建程序 ...

随机推荐

  1. hdu_5965_扫雷(递推)

    题目链接:hdu_5965_扫雷 题意: 中文,还是自己看吧. 题解: 现场赛这题用的状压DP过的,不过现在想想当时还确实想复杂了,冷静下来仔细思靠一下,其实第i-1个确定了,那么第i个也是确定的,可 ...

  2. 浙大pat 1031题解

    1031. Hello World for U (20) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Giv ...

  3. Struts文件上传

    首先要加入上传文件需要的jar文件 commons-fileupload-1.2.1.jar commomons-io-1.3.2.jar不同版本的strutsjar文件的版本也可能不同,一般在配置s ...

  4. Lucene基础(1)

    下一篇: Lucene基础(2) 一.Lucene介绍 http://www.kailing.pub/index/columns/colid/16.html Documentation:http:// ...

  5. MaskEdit组件的EditText属性和Text属性

    MaskEdit组件主要是EditMask属性 是string属性. 掩码字符串EditMask属性分为3个部分,分别用分号隔开,形式是“XXXXX;X;X” 第一部分是掩码字符串的主要部分,它确定输 ...

  6. 转Rollback后undo到底做了些什么?

    转自:http://biancheng.dnbcw.info/oracle/309191.html Rollback后undo到底做了些什么? 从概念上讲,undo正好与redo相对.当你对数据执行修 ...

  7. Delphi中,FALSE 和 nil ,true 和 nil,0的区别

    True和False是布尔型(Boolean)的值,就是"是"或"否"的意思.nil就是空,一般用于指针或对象变量,指对针或对象对象一般初始化为nil或者释放后 ...

  8. PHP文本路径转换为链接文字

    <?php /** * 文本路径转换为有链接的文字 * @param string $str 转换内容 * @return string */ function urlToLink($str) ...

  9. LeetCode OJ 59. Spiral Matrix II

    Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For ...

  10. 使用WTL的消息反射封装CEdit实现监听控件文本改变事件

    消息反射机制可以使对消息的处理都集中在控件类中,以CEdit的EN_CHANGE消息为例: /*MyEdit.h*/ class CMyEdit:public CWindowImpl<CMyEd ...