Android OpenGL
1、什么是OpenGL?
OpenGL是个专业的3D程序接口,是一个功能强大,调用方便的底层3D图形库。OpenGL的前身是SGI公司为其图形工作站开的IRISGL。IRISGL是一个工业标准的3D图形软件接口,功能虽然强大但是移植性不好,于是SGI公司便在IRISGL的基础上开发OpenGL。具体详细的介绍请点击这里。
2、OpenGL的发展历程
1992年7月发布了OpenGL1.0版本,并与微软共同推出WindowsNT版本的OpenGL。
1995年OpenGL1.1版本面市,加入了新功能,并引入了纹理特性等等。
一直到2009年8月Khronos小组发布了OpenGL3.2,这是一年以来OpenGL进行的第三次重要升级。
具体特点及功能、OpenGL现状、发展历程、OpenGL规范、编程入门请点击这里。
3、OpenGLES简介
Android3D引擎采用的是OpenGLES。OpenGLES是一套为手持和嵌入式系统设计的3D引擎API,由Khronos公司维护。在PC领域,一直有两种标准的3DAPI进行竞争,OpenGL和DirectX。一般主流的游戏和显卡都支持这两种渲染方式,DirectX在Windows平台上有很大的优势,但是OpenGL具有更好的跨平台性。
由于嵌入式系统和PC相比,一般说来,CPU、内存等都比PC差很多,而且对能耗有着特殊的要求,许多嵌入式设备并没有浮点运算协处理器,针对嵌入式系统的以上特点,Khronos对标准的OpenGL系统进行了维护和改动,以期望满足嵌入式设备对3D绘图的要求。
4、AndroidOpenGLES简介
Android系统使用OpenGL的标准接口来支持3D图形功能,android3D图形系统也分为java框架和本地代码两部分。本地代码主要实现的OpenGL接口的库,在Java框架层,javax.microedition.khronos.opengles是java标准的OpenGL包,android.opengl包提供了OpenGL系统和AndroidGUI系统之间的联系。
5、Android支持OpenGL列表
1、GL
2、GL10
3、GL10EXT
4、GL11
5、GL11EXT
6、GL11ExtensionPack
我们将使用GL10这个类开始接触OpenGL,探索3D领域。
6、一步一步实现自己的Renderer类
在Android中我们使用GLSurfaceView来显示OpenGL视图,该类位于android.opengl包里面。它提供了一个专门用于渲染3D的接口Renderer。接下来我们就来一步步构建自己的Renderer类。
1、为Renderer类赶回命名空间
importandroid.opengl.GLSurfaceView.Renderer;
2、新建一个类来实现Renderer接口,代码如下:
publicclassThreeDGlimplementsRenderer
{
}
3、如上代码所写,程序实现了Renderer类,则必须重写以下方法
publicvoidonDrawFrame(GL10gl)
{
}
publicvoidonSurfaceChanged(GL10gl,intwidth,intheight)
{}
publicvoidonSurfaceCreated(GL10gl,EGLConfigconfig)
{}
4、当窗口被创建时需要调用onSurfaceCreate,我们可以在这里对OpenGL做一些初始化工作,例如:
//启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
//黑色背景
gl.glClearColor(0,0,0,0);
//设置深度缓存
gl.glClearDepthf(1.0f);
//启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
//所作深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
//告诉系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
glHint用于告诉OpenGL我们希望进行最好的透视修正,这会轻微地影响性能,但会使得透视图更好看。
glClearColor设置清除屏幕时所用的颜色,色彩值的范围从0.0f~1.0f大小从暗到这的过程。
glShadeModel用于启用阴影平滑度。阴影平滑通过多边形精细地混合色彩,并对外部光进行平滑。
glDepthFunc为将深度缓存设想为屏幕后面的层,它不断地对物体进入屏幕内部的深度进行跟踪。
glEnable启用深度测试。
5、当窗口大小发生改变时系统将调用onSurfaceChange方法,可以在该方法中设置OpenGL场景大小,代码如下:
//设置OpenGL场景的大小
gl.glViewport(0,0,width,height);
6、场景画出来了,接下来我们就要实现场景里面的内容,比如:设置它的透视图,让它有种越远的东西看起来越小的感觉,代码如下:
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
//设置视口的大小
gl.glFrustumf(-ratio,ratio,-1,1,1,10);
//选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
//重置模型观察矩阵
gl.glLoadIdentity();
gl.glMatrixMode(GL10.GL_PROJECTION);指明接下来的代码将影响projectionmatrix(投影矩阵),投影矩阵负责为场景增加透视度。
gl.glLoadIdentity();此方法相当于我们手机的重置功能,它将所选择的矩阵状态恢复成原始状态,调用glLoadIdentity();之后为场景设置透视图。
gl.glMatrixMode(GL10.GL_MODELVIEW);指明任何新的变换将会影响modelviewmatrix(模型观察矩阵)。
gl.glFrustumf(-ratio,ratio,-1,1,1,10);此方法,前面4个参数用于确定窗口的大小,而后面两个参数分别是在场景中所能绘制深度的起点和终点。
7、了解了上面两个重写方法的作用和功能之后,第三个方法onDrawFrame从字面上理解就知道此方法做绘制图操作的。嗯,没错。在绘图之前,需要将屏幕清除成前面所指定的颜色,清除尝试缓存并且重置场景,然后就可以绘图了,代码如下:
//清除屏幕和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
//重置当前的模型观察矩阵
gl.glLoadIdentity();
8、Renderer类在实现了上面的三个重写之后,在程序入口中只需要调用
Rendererrender=newThreeDGl(this);
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
GLSurfaceViewgview=newGLSurfaceView(this);
gview.setRenderer(render);
setContentView(gview);
}
即可将我们绘制的图形显示出来。
下面分享一段使用Renderer类绘制的三角形和四边形的代码:
OpenGL参考代码
packagecom.terry;
importjava.nio.IntBuffer;
importjavax.microedition.khronos.egl.EGLConfig;
importjavax.microedition.khronos.opengles.GL10;
importandroid.opengl.GLSurfaceView.Renderer;
publicclassGLRenderimplementsRenderer{
floatrotateTri,rotateQuad;
intone=0x10000;
//三角形的一个顶点
privateIntBuffertriggerBuffer=IntBuffer.wrap(newint[]{
0,one,0,//上顶点
-one,-one,0,//左顶点
one,-one,0//右下点
});
//正方形的四个顶点
privateIntBufferquateBuffer=IntBuffer.wrap(newint[]{
one,one,0,
-one,-one,0,
one,-one,0,
-one,-one,0
});
privateIntBuffercolorBuffer=IntBuffer.wrap(newint[]{
one,0,0,one,
0,one,0,one,
0,0,one,one
});
@Override
publicvoidonDrawFrame(GL10gl){
//TODOAuto-generatedmethodstub
//清除屏幕和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
//重置当前的模型观察矩阵
gl.glLoadIdentity();
//左移1.5单位,并移入屏幕6.0
gl.glTranslatef(-1.5f,0.0f,-6.0f);
//设置旋转
gl.glRotatef(rotateTri,0.0f,1.0f,0.0f);
//设置定点数组
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//设置颜色数组
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glColorPointer(4,GL10.GL_FIXED,0,colorBuffer);
//设置三角形顶点
gl.glVertexPointer(3,GL10.GL_FIXED,0,triggerBuffer);
//绘制三角形
gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
//绘制三角形结束
gl.glFinish();
/***********************/
/*渲染正方形*/
//重置当前的模型观察矩阵
gl.glLoadIdentity();
//左移1.5单位,并移入屏幕6.0
gl.glTranslatef(1.5f,0.0f,-6.0f);
//设置当前色为蓝色
gl.glColor4f(0.5f,0.5f,1.0f,1.0f);
//设置旋转
gl.glRotatef(rotateQuad,1.0f,0.0f,0.0f);
//设置和绘制正方形
gl.glVertexPointer(3,GL10.GL_FIXED,0,quateBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
//绘制正方形结束
gl.glFinish();
//取消顶点数组
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//改变旋转的角度
rotateTri+=0.5f;
rotateQuad-=0.5f;
}
@Override
publicvoidonSurfaceChanged(GL10gl,intwidth,intheight){
//TODOAuto-generatedmethodstub
floatratio=(float)width/height;
//设置OpenGL场景的大小
gl.glViewport(0,0,width,height);
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
//设置视口的大小
gl.glFrustumf(-ratio,ratio,-1,1,1,10);
//选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
//重置模型观察矩阵
gl.glLoadIdentity();
}
@Override
publicvoidonSurfaceCreated(GL10gl,EGLConfigconfig){
//TODOAuto-generatedmethodstub
//启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
//黑色背景
gl.glClearColor(0,0,0,0);
//设置深度缓存
gl.glClearDepthf(1.0f);
//启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
//所作深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
//告诉系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
}
}