openGL:
openGL是用C语言实现的,而我们作为安卓开发者,严格来讲,我们使用的是es,也就是openGL es,原因无非就像数据库一样,安卓上使用的数据库永远不可能是Mysql之类的,因为终端讲究轻量。
接下来我们来创建第一个openGL项目:
首先我们来了解一下GLSurfaceView这个类,这个类相当于是在屏幕上的一个模板,如下图。
所以,创建一个类继承GLSurfaceView之后,我们就可以new出GLSurfaceView类的对象,调用GLSurfaceView类的对象的setRenderer()方法,就可以对GLSurfaceView进行渲染,而我们的主要工作是,如何进行渲染。
class MyGLSurfaceView extends GLSurfaceView{ public MyGLSurfaceView(Context context) { super(context); } public MyGLSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); } }
那么就要自定义一个渲染器:new一个类实现Renderer,需重写三个方法:onSurfaceCreated,onSurfaceChanged和onDrawFrame。
//自定义渲染器 class MyRenderer implements GLSurfaceView.Renderer{ //表层创建时调用 @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { //设置清屏色 gl.glClearColor(0, 0, 0, 1); //启用顶点缓冲区 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); } //当表层size改变时调用 @Override public void onSurfaceChanged(GL10 gl, int width, int height) { //设置视口,输出画面的区域。 gl.glViewport(0,0,width,height); //宽高比 float ratio = (float)width/(float)height; //矩阵模式,投影矩阵,openGL基于状态机。 gl.glMatrixMode( GL10.GL_PROJECTION ); //加载单位矩阵 gl.glLoadIdentity(); //设置平截头体 gl.glFrustumf(-1f,1f,-ratio,ratio,3,7); //-1f,1f为平截头体左右大小比,-ratio,ratio为平截头体底面和顶面,3,7为近平面和原平面距离 } //绘图调用 @Override public void onDrawFrame(GL10 gl) { //清除颜色缓冲区。 gl.glClear(GL10.GL_COLOR_BUFFER_BIT); //模型视图矩阵。 gl.glMatrixMode( GL10.GL_MODELVIEW ); //加载单位矩阵。 gl.glLoadIdentity(); //0,0,5:放置眼球的坐标。 //0,0,0:眼球观察的中心点坐标。 //0,1,0:指定眼球向上的向量。 GLU.gluLookAt(gl,0,0,5,0,0,0,0,1,0); /** * 画三角形 */ //三角形顶点坐标 float [] coords = { 0f,0.5f,0f, -0.5f,-0.5f,0f, 0.5f,-0.5f,0f }; //分配字节缓存空间,存放顶点坐标数据。 ByteBuffer ibb = ByteBuffer.allocateDirect(coords.length * 4); //设置顺序(本地顺序)。 ibb.order(ByteOrder.nativeOrder()); //放置顶点数组。 FloatBuffer fbb = ibb.asFloatBuffer(); fbb.put(coords); //定位指针位置,从该位置开始读取顶点数据。 ibb.position(0); //设置绘图颜色:红色。 gl.glColor4f(1f,0,0,1f); //3→三维点,使用三个坐标表示一个点。 //每个点的数据类型。 //0→跨度。 //ibb指定缓冲区。 gl.glVertexPointer(3,GL10.GL_FLOAT,0,ibb); //画数组 gl.glDrawArrays(GL10.GL_TRIANGLES,0,3); } }显而易见,onSurfaceCreated和 onSurfaceChanged都是在做初始化工作,关键的是onDrawFrame方法:
需要注意的是,onSurfaceChanged中设置的平截头体,所谓平截头体就是一个类似棱锥的区域,如下图:
最左边的眼睛通过中间墙上的孔,可以看得见与孔相同比例的空间,那么墙上的孔到墙后景物中间的四棱锥,就是一个平截头体。墙上的孔叫近平面,后方景物叫远平面。因为光是直射的,所以,我们只要指定好近平面的比例,以及图中两段红线的比例,那么就能确定远平面,继而确定平截头体。
确定了平截头体之后,就要关注onDrawFrame方法,类似于拍照的过程,我确定了要拍什么之后,还是要确定拍照时候要确定相机的位置,相机的朝向,相机的反正。这个三个属性就对应了程序中的GLU.gluLookAt()方法。详细参数见代码注释。
通过这几步之后,还是不能拍照,因为我们还有一些参数没有设置,比如绘图颜色。上例程序中是画了一个三角形,那么还需指定三角形的三点坐标等等,具体细节代码中注释的很详细,不再赘述。
上例代码运行效果图: