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);

}

}

相关推荐