配置 OpenGL ES 的环境

本篇文章属于 使用 OpenGL ES 进行图形绘制 这个系列的第一篇文章,主要内容是介绍在 Android 应用使用 OpenGL ES 时需要配置的开发环境和整体流程说明。

要在 Android 应用中使用 OpenGL ES 绘制图像,我们必须为它们创建一个 View 容器。一种比较直接的方法是实现 GLSurfaceView 类和 GLSurfaceView.Renderer 类。其中 GLSurfaceView 是一个视图容器,它用来存放使用 OpenGL 绘制的图形,而 GLSurfaceView.Renderer 则用来控制在该视图内容的绘制(渲染器)。关于这两个类的更多信息,可以阅读 OpenGL ES 开发手册。

Note: GLSurfaceView 是一个 View container,用来存放绘制的图像。
GLSurfaceView.Renderer 是用来控制 View 中绘制的内容的渲染器。

使用 GLSurfaceView 是一种将 OpenGL ES 集成到应用中的方法之一。对于一个全屏的或者接近全屏的图形 View,使用它是一个理想的选择。开发者如果希望把 OpenGL ES 的图形集成在布局的一小部分里面,那么可以考虑使用 TextureView。对于喜欢自己动手实现的开发者来说,还可以通过使用
SurfaceView 搭建一个 OpenGL ES View,但这将需要编写更多的代码。

下面将展示如何在一个 Activity 中完成 GLSurfaceViewGLSurfaceView.Renderer 的最简单直接的实现。

1. 1 在 Manifest 配置文件中声明使用 OpenGL ES

为了让应用能够使用 OpenGL ES 2.0 接口,我们必须将下列声明添加到 Manifest 配置文件当中:

<!--0x00020000 代表使用 OpenGL ES 2.0 接口-->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />

如果应用要使用纹理压缩(Texture Compression),则必须声明对纹理压缩格式的支持,这样确保应用仅安装在可以兼容的设备上:

<!--纹理压缩格式格式声明-->
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />

纹理压缩通过减少内存需求并更有效地利用内存带宽,可以显着提高 OpenGL 应用程序的性能。更多关于纹理压缩的内容可以阅读 OpenGL 开发手册

1.2 为 OpenGL ES 图形创建一个 Activity

使用 OpenGL ES 的 Android 应用跟其它类型的应用主要的区别体现在 Activity 布局内容上的差异。通常我们会使用 TextViewButton等已经封装好的控件。而如果使用 OpenGL ES 的我们就得依赖 GLSurfaceView 来自己实现了。

所以最简单的使用方式是直接创建一个 GLSurfaceView 实例,并把它作为 ContentView 设置到 Activity 中。

public class OpenGLSample01Activity extends AppCompatActivity {

    GLSurfaceView mGLSurfaceView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle("OpenGLSample01");

        // Create a GLSurfaceView instance and set it
        // as the ContentView for this Activity.
        mGLSurfaceView = new MyGLSurfaceView(this);
        setContentView(mGLSurfaceView);
    }
}

OpenGL ES 2.0 需要Android 2.2(API Level 8)或更高版本的系统,所以确保你的Android项目的 API 版本满足该要求。

1.3 构建一个 GLSurfaceView 对象

GLSurfaceView 是一种比较特殊的 View,我们可以在该 View 中绘制 OpenGL ES 图形,不过它自己并不做太多和绘制图形相关的任务。绘制对象的任务是由你在该 View 中配置的 GLSurfaceView.Renderer 所控制的。因此在实际开发中不建议直接使用 GLSurfaceView 来创建实例。

事实上,GLSurfaceView 的核心代码非常简短,你可能会直接创建一个未经修改的 GLSurfaceView 实例,不过请不要这么做,因为我们需要继承该类来捕捉触控事件,这方面知识会在 响应触摸事件 中做进一步的介绍。

class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;

    public MyGLSurfaceView(Context context){
        super(context);

        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2);

        mRenderer = new MyGLRenderer();

        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(mRenderer);
    }
}

另一个对于 GLSurfaceView 的可选选项是将渲染模式设置为:GLSurfaceView.RENDERMODE_WHEN_DIRTY,其含义是仅在你的绘制数据发生变化时才在视图中进行绘制操作:

// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

如果选用这一配置选项,那么除非调用了 requestRender(),否则 GLSurfaceView 不会被重新绘制,这样做可以让应用的性能及效率得到提高。

1.4 构建一个渲染器类

在一个使用 OpenGL ES 的应用中,必定少不了 GLSurfaceView.Renderer 类的实现。该类会控制和其相关联的 GLSurfaceView 的绘制行为和内容,Renderer 这个类中有三个方法会被系统调用,所以需要实现下面三个方法:

  • onSurfaceCreated():调用一次,用来配置 View 的 OpenGL ES 环境。
  • onDrawFrame():每次重新绘制View时被调用。
  • onSurfaceChanged():如果View的几何形态发生变化时会被调用,例如当设备的屏幕方向发生改变时。

下面是一个非常基本的 OpenGL ES 渲染器的实现,它仅仅在GLSurfaceView 中画一个黑色的背景:

public class MyGLRenderer implements GLSurfaceView.Renderer {

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }

    public void onDrawFrame(GL10 unused) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
}

通过上述代码,我们完成一个完整的 OpenGL ES 简单使用场景,程序运行起来会是一个黑色的背景。

下面来简单回顾一下在应用中使用 OpenGL ES 的整个流程:

  • 在 Manifest 中对使用 OpenGL ES 进行声明
  • 给 OpenGL ES 绘制的图像创建 Activity
  • 创建一个 GLSurfaceView 对象并设置到 Activity 中
  • 创建一个 Renderer 类实现绘制逻辑,并设置到 GLSurfaceView

文章中所有的代码示例都已放在 Github 上,可以去项目 OpenGL-ES-Learning 中查看 。

通过基于上面的内容,相信你对于如何使用 OpenGL 绘制图形有了基本的认识和铺垫。当然,这些都是相当基础的知识,如果你对 OpenGL ES 接口很熟悉,那么你现在就可以在应用中构建一个 OpenGL ES 的环境并绘制图形了。如果你希望获取更多关于 OpenGL 的内容,请继续看后面的内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容