【Android学习系列】 OpenGL开发教程一
来源:互联网 发布:淘宝网高领羊毛衫 编辑:程序博客网 时间:2024/04/26 05:35
之前一直想去看看OPEN-GL的文章,也想了解下在Android平台下是如何利用它去开发一个3D场景,比如游戏,或虚拟场景。看了gongziya的博客,他记录自己学习Android平台的OPENGL开发的过程,于是也想记录下自己的一些轨迹,也算是对学习的一个总结。
本文基本上是参考gongziya的文章(http://gongziya.com/721/android%E7%9A%84opengl%E6%95%99%E7%A8%8B%E7%AC%AC%E4%B8%80%E8%AF%BE%EF%BC%9A%E5%88%9B%E5%BB%BA%E7%AA%97%E5%8F%A3/)
在对该文进行测试,理解的基础上,逐渐加入自己的一些困惑和想法,希望能最终形成一个适合自己的文档。
【目的】
了解OPENGL的开发过程,通过学习系列教程,能顺利开发常规的3D游戏,能了解OPENGL的机理;如果能将OPENGL和meeting中的PD,AS结合起来,那更是一件美妙的事情。
【计划】
9.10-14,学习完gongziya的教程;每日作出总结。
9.17-21,。。。【更新中】
***********************开始吧**********************************
Android下OPENGL的开发,并不需要特别的环境,只要Android的SDK即可。gongziya是熟悉OPENGL,而不大了解Andrroid,我则刚好相反,个人感觉应该对OPENGL有一定的了解,才能很好的理解设计的思路。
【第一部分 GLSurfaceView】
Android为我们提供了GLSurfaceView,能方便地显示自己的OPENGL视图,在GLSurfaceView类中包含了一个专门用于渲染3D的接口Renderer。所以想要使用OPENGL渲染,必要创建一个OPENGLRender类,实现这个接口:
class OpenGLRender implements Renderer {@Overridepublic void onDrawFrame(GL10 gl) {// draw what you want to draw}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// when the screen changed, do the things here. For example, rotate the screen.}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// do the initialize work here.} }
这个接口中的三个方法作用分别如下:
onDrawFrame:绘图的代码;
onSurfaceChanged:屏幕发生变化时的操作,旋转等;
onSurfaceCreated: 初始化工作
将这个Render应用到Activity的代码很简单:
Renderer render = new OpenGLRenderer();//创建render public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); GLSurfaceView glView = new GLSurfaceView(this);//创建GLSurfaceView glView.setRenderer(render);//设置render,使之生效 setContentView(glView);//把glview设置为屏幕内容}
这样,如何实现Render中的三个方法,就成为了重中之重,也是我们发挥想象力的地方。
【第二部分 Renderer 基本方法】
(1) onSurfaceCreated
在这里进行初始化工作,设置各个参数:
gl.glClearColor: 设置屏幕背景;
gl.glShadeModel: 设置阴影平滑;
//设置深度缓存,通过深度缓存可以让OpenGL知道场景中物体的深度关系,这样我们在绘制物体时,不会把后面的物体绘制到前面的物体上。
gl.glClearDepthf, gl.glEnable, gl.glDepthFunc,主要由这三个方法控制。
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); //设置透视性能----这个有什么好处?
Q1:初始化中,要进行哪些必要的设置?
(2) onSurfaceChanged
当屏幕发生改变的时候,需要在这里进行相关的操作,不管如何,该方法至少调用一次。
// Sets the current view port to the new size.gl.glViewport(0,0, width, height);// Select the projection matrixgl.glMatrixMode(GL10.GL_PROJECTION); -----设置投影矩阵// Reset the projection matrixgl.glLoadIdentity();--------------------------重置投影矩阵// Calculate the aspect ratio of the windowgl.glFrustumf(-ratio, ratio, -1,1,1,10);---设置视口大小 参考http://gongziya.com/693/opengl中的投影和视口变换/// Select the modelview matrixgl.glMatrixMode(GL10.GL_MODELVIEW); -----------选择模型观察矩阵// Reset the modelview matrixgl.glLoadIdentity();---------------------------重置模型观察矩阵
Q2:选择和重置投影矩阵,模型观察矩阵,有什么作用?窗口,视口的概念是什么?
(3) onDrawFrame
绘制屏幕中的图形。
// 重置当前的模型观察矩阵gl.glLoadIdentity();// 左移 1.5 单位,并移入屏幕 6.0gl.glTranslatef(-1.5f,0.0f, -6.0f);-------------------设置图形位置?//启用定点数组gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);----------顶点数组是什么概念?// 设置三角形顶点 (int size, int type, int stride, Buffer pointer)gl.glVertexPointer(3, GL10.GL_FLOAT, 0,TrianBuffer);---3:xyz三维;type表明是浮点型;stride连续顶点之间的偏移量??pointer是顶点坐标数据的顶点缓存。strider和pointer如何理解?//绘制三角形glDrawArrays(intmode,intfirst,intcount) ---count标明数组个数,从索引为0开始,总共有3个gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);/* 渲染正方形 */// 重置当前的模型观察矩阵gl.glLoadIdentity();// 左移 1.5 单位,并移入屏幕 6.0gl.glTranslatef(1.5f,0.0f, -6.0f);//设置和绘制正方形gl.glVertexPointer(3, GL10.GL_FLOAT, 0, QuaterBuffer);gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);//取消顶点数组gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);调用glLoadIdentity()之后,您实际上将当前点移到了屏幕中心,X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。中心左面的坐标值是负值,右面是正值。移向屏幕顶端是正值,移向屏幕底端是负值。移入屏幕深处是负值,移出屏幕则是正值。
glTranslatef(x,y,z)沿着 X,Y 和 Z 轴移动。根据前面的次序,下面的代码沿着X轴左移1.5个单位,Y轴不动(0.0f),最后移入屏幕6.0f个单位。注意在glTranslatef(x,y,z)中当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。
【第三部分 添加颜色和动画效果】
颜色和动画,都是属于onDrawFrame里面的内容,也就是实际上在屏幕上要显示出来的东西。
(1) 添加颜色
添加颜色的逻辑比较简单,主要分为四步:构造颜色数组(你要给该图形填充什么颜色);启用颜色数组;绘画;关闭颜色数组;
A. 构建颜色数组
//三角形的顶点颜色值(r,g,b,a)private float colorvertices[] = { 1.0f,0.0f,0.0f,1.0f, 0.0f,1.0f,0.0f,1.0f, 0.0f,0.0f,1.0f,1.0f, };private FloatBuffer ColorBuffer;//给colorBuffer赋值,这个操作同之前构造三角形,四边形的动作是一样,需要构造一个能被OPENGL接收的数据类型Buffer
//下面设置三角形颜色数据ByteBuffer cbb = ByteBuffer.allocateDirect(colorvertices.length * 4);cbb.order(ByteOrder.nativeOrder());ColorBuffer = cbb.asFloatBuffer();ColorBuffer.put(colorvertices);ColorBuffer.position(0);
B. 启用颜色数组
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);C. 绘画
gl.glColorPointer(4, GL10.GL_FLOAT, 0, ColorBuffer);D. 关闭颜色数组
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
【注意】启用和关闭的动作是成对出现的;如果是单色填充,则不需要启用颜色数组这个操作。直接填充即可。 gl.glColor4f(0.5f, 0.5f, 1.0f, 1.0f);
(2) 添加动画
动画旋转的操作,主要通过glRotatef(Angle,Xvector,Yvector,Zvector)来实现,它负责让对象绕某个轴旋转。这个命令有很多用处(用处体现在哪儿?)。
Angle 通常是个变量代表对象转过的角度。
Xvector,Yvector和Zvector三个参数则共同决定旋转轴的方向。形象地理解,可以根据这三个参数画一个轴,图形就是围绕该轴转动。
//设置旋转gl.glRotatef(rotateTri, 0.0f, 1.0f, 0.0f);
【注意】通过该例子明白,onDrawFrame是每帧都会调用的,不断刷新;gl.glRotatef的动作,要放置在gl.glTranslatef 动作之后,即先定位置,再旋转;
我们说了很久的顺时针,逆时针画图,到底有什么用呢
gl.glEnable(GL10.GL_CULL_FACE);
//设置openggl有剔除效果,就是看不到的面就不画,当然可以增加效率
gl.glFrontFace(GL10.GL_CCW);
//设置逆时针方向为正面
gl.glCullFace(GL10.GL_BACK);
//设置背面被剔除,不画
Cull就是剔除的意思
- 【Android学习系列】 OpenGL开发教程一
- 【Android学习系列】OpenGL开发教程二
- Android OpenGL ES 开发教程(一)
- OpenGL ES学习系列教程
- Android OpenGL ES 简明开发教程一:概述
- Android OpenGL ES 简明开发教程一:概述
- Android OpenGL ES 简明开发教程一:概述
- Android OpenGL ES 简明开发教程一:概述
- Android OpenGL ES 简明开发教程一:概述
- Android OpenGL ES2.0编程教程系列之创建OpenGL ES环境(一)
- 学习OpenGL系列一 窗口
- Android学习开发之路~~系列教程
- 台湾一所大学的OPENGL 系列教程
- 如何使用Android Studio开发Gradle插件系列教程(一)
- android 学习系列教程
- Ubuntu 下OpenGL学习系列一
- Android OpenGL学习笔记(一)
- Android OpenGL学习笔记(一)
- C51变量的存储
- HTTP协议详解
- 使用 Ant 实现批量打包Android应用
- 不要在一门技术上吊死
- 小伤风没必要用抗菌素
- 【Android学习系列】 OpenGL开发教程一
- 上传图片预览
- 心醉七夕
- 调用Google地图
- 用户控件 + ScriptManager 实现点击后弹出窗口且窗口坐标追随点击位置效果
- linux变量
- Portal-Basic Java Web 应用开发框架(源码、示例及文档)
- 【转】android数据库升级
- IIS7上部署Asp.Net4.0时UrlRouting的若干问题