且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

更新时间:2022-03-04 05:48:01

本节书摘来自华章出版社《OpenGL ES应用开发实践指南:Android卷》一 书中的第1章,第1.3节,作者:(美)Kevin Brothaler ,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

1.3 初始化OpenGL

下一步就是使用一个特殊的类GLSurfaceView初始化OpenGL。GLSurfaceView会处理OpenGL初始化过程中比较基本的操作,如配置显示设备(display)以及在后台线程中渲染;渲染是在显示设备中一个称为“surface”的特定区域完成的,有时也称为视口(viewport)。
GLSurfaceView类也使得处理标准Android Activity生命周期变得容易了;在Android里,任何Activity都可以创建(create)和销毁(destroy),并且在用户切换到其他Activity时暂停(pause),在切换回来时继续(resume)。根据这个生命周期,在Activity被暂停的时候,我们需要释放OpenGL的资源;GLSurfaceView为此提供了很多辅助方法。
在EDBurnette所写的《Hello, Android》里,你可以学到更多关于Activity生命周期的内容。
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

纹理视图
在幕后,GLSurfaceView实际上为它自己创建了一个窗口(window),并在视图层次(View Hierarchy)上穿了个“洞”,让底层的OpenGL surface显示出来。对于大多数使用情况,这就足够了;但是,GLSurfaceview与常规视图(view)不同,它没有动画或者变形特效,因为GLSurfaceView是窗口(window)的一部分。
从Android 4.0 Ice Cream Sandwich开始,Android提供了一个纹理视图(TextureView),它可以渲染OpenGL而不用创建单独的窗口或打洞了,这就意味着,这个视图像一个常规窗口一样,可以被操作,且有动画和变形特效。但是,TextureView类没有内置OpenGL初始化操作,要想使用TextureView,一种方法是执行自定义的OpenGL初始化,并在TextureView上运行,另外一种方法是把GLSurfaceView的源代码拿出来,把它适配到TextureView上。

1.3.1 创建GLSurfaceView实例

打开前面自动生成的Activity类FirstOpenGLProjectActivity。按下“Ctrl+Shift+T”快捷键,“Open Type”对话框就会弹出来,然后输入“FirstOpenGLProjectActivity”,当那个类显示出来时,就选择它。
Eclipse键盘快捷键
在Mac或者Linux平台上,快捷键可能与Windows平台不同;比如,快捷键“Ctrl+Shift+O”,在Windows平台上,它是用来组织和查找新的Java 导入(import)的;在Mac平台上就是。可以通过菜单“Help→Key Assist”选择按键辅助功能查看各个平台的键绑定。
现在看起来没有多少代码:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

我们给这个Activity添加一个GLSurfaceView实例,这样就可以初始化OpenGL。让我们在类的顶部加入如下两个新的成员变量:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

我们需要导入GLSurfaceView类,因此,按“Ctrl+Shift+O”快捷键组织导入,并把这个新类放到代码里;每次加入一个新的类引用,并且它需要被导入时,我们都要做这一步。我们将用rendererSet记住GLSurfaceView是否处于有效状态。让我们从代码中移除setContentView()的调用,并加入如下代码初始化glSurfaceView:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

1.3.2 检查系统是否支持OpenGL ES 2.0

因为我们只为2.0版本写代码,我们要做的下一件事就是检查系统是否实际支持OpenGL ES 2.0。让我们添加如下几行代码到onCreate()函数中:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

首先,我们需要Android ActivityManager的一个引用,用它获取设备配置信息,然后,取出reqGlEsVersion变量检查OpenGL ES版本号。如果版本号为0×20000或后续版本,我们就可以使用 OpenGL ES 2.0的API了。
但是这段代码实际上不能在模拟器上工作,因为GPU模拟部分有缺陷;为了使代码在模拟器上正常工作,我们要按如下代码修改那个检查条件:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

这段代码测试当前设备是不是模拟器,如果是,就假定它支持OpenGL ES 2.0。要确保程序能运行,模拟器一定要配置OpenGL ES 2.0,参见1.1.1节。

1.3.3 为OpenGL ES 2.0配置渲染表面

下一步就是配置渲染表面(rendering surface),添加如下几行代码:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

如果设备支持OpenGL ES 2.0,我们就通过调用setEGLContextClientVersion(2)配置这个surface视图;然后调用setRenderer()传进自定义Renderer类的一个新实例,稍后,我们会看到如何创建这个Renderer类,同时这段代码通过设置rendererSet为true记住渲染器(renderer)已经设置过了。当surface创建或者发生变化的时候,以及要绘制一幅新帧时,渲染器都会被GLSurfaceView调用。
如果设备不支持OpenGL ES 2.0,怎么办呢?也可以添加一个支持OpenGL ES 1.0的回退的渲染器,但是,这种情形现在已经很少见了,可能不值得付出这样的努力。根据Android开发者统计板,仅有大约9%的设备只支持OpenGL ES 1.1,这个数字还在随着时间不断缩减。如果一个设备不支持OpenGL ES 2.0,公开发布的应用应该在这个设备的应用程序市场中被隐藏起来,在14.1.6节中,我们会学到这点。
我们需要添加另外一个调用把GLSurfaceView加入到这个activity中,并把它显示到屏幕上,在onCreate()函数结尾处,用如下代码替换旧的调用setContentView():
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

1.3.4 处理Android Activity生命周期的事件

我们还需要处理Android Activity生命周期的事件,否则,如果用户切换到另外一个应用,应用就会崩溃;加入如下方法让这个Activity类变得完整:
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL

这些方法非常重要,有了它们 ,这个surface视图才能正确暂停并继续后台渲染线程,同时释放和续用OpenGL上下文。如果它没有做这些,应用程序可能会崩溃,并被Android终止;我们还要保证渲染器也设置了,否则调用这些方法也会引起程序崩溃。