【Android音视频学习之路(九)】OpenGL ES 简单入门

778 阅读6分钟

【Android音视频学习之路(一)】如何在 Android 平台绘制一张图片

【Android音视频学习之路(二)】AudioRecord API详解及应用

【Android音视频学习之路(三)】AudioTrack 使用与详解

【Android音视频学习之路(四)】Camera 的使用

【Android音视频学习之路(五)】MediaExtractor和MediaMuxer讲解

【Android音视频学习之路(六)】 MediaCodec 简单讲解

【Android音视频学习之路(七)】音视频录制流程实践

【Android音视频学习之路(八)】YUV格式初探

“这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

谈到OpenGL ES,首先我们应该先去了解一下Android的基本架构,基本架构下图:

image.png 在这里我们可以找到Libraries里面有我们目前要接触的库,即OpenGL ES。

根据上图可以知道Android 目前是支持使用开放的图形库的,特别是通过OpenGL ES API来支持高性能 的2D和3D图形。OpenGL是一个跨平台的图形API。为3D图形处理硬件指定了一个标准的软件接口。 OpenGL ES 是适用于嵌入式设备的OpenGL规范。

Android 支持OpenGL ES API版本的详细状态是:

  • OpenGL ES 1.0 和 1.1 能够被Android 1.0及以上版本支持
  • OpenGL ES 2.0 能够被Android 2.2及更高版本支持
  • OpenGL ES 3.0 能够被Android 4.3及更高版本支持
  • OpenGL ES 3.1 能够被Android 5.0及以上版本支持

基本介绍

Android 能够通过framework框架提供的API或者NDK来支持OpenGL。本文重点介绍框架提供的接口来 使用OpenGL的方式,有关于NDK方面的信息,可以自行去官方文档进行了解。 在Android框架里面两个基本的类允许你使用OpenGL ES API创建和操作图形: GLSurfaceView 和 GLSurfaceView.Renderer。如果您的目标是在Android程序中使用OpenGL,那么首先需要做的事情就 是了解这两个类。

GLSurfaceView

这是一个视图类,你可以使用OpenGL API来绘制和操作图形对象,这一点在功能上很类似于 SurfaceView。你可以通过创建一个SurfaceView的实例并添加你的渲染器来使用这个类。但是如果想要 捕捉触摸屏的事件,则应该扩展GLSurfaceView以实现触摸监听器。关于实现触摸监听器的方式,我们 会在后面的文章中进行讲解。

GLSurfaceView.Renderer

此接口定义了在GLSurfaceView中绘制图形所需的方法。您必须将此接口的实现作为单独的类提供,并 使用GLSurfaceView.setRenderer()将其附加到您的GLSurfaceView实例。 GLSurfaceView.Renderer要求实现以下方法:

  • onSurfaceCreated():创建GLSurfaceView时,系统调用一次该方法。使用此方法执行只需 要执行一次的操作,例如设置OpenGL环境参数或初始化OpenGL图形对象。
  • onDrawFrame():系统在每次重画GLSurfaceView时调用这个方法。使用此方法作为绘制 (和重新绘制)图形对象的主要执行方法。
  • onSurfaceChanged():当GLSurfaceView的发生变化时,系统调用此方法,这些变化包括 GLSurfaceView的大小或设备屏幕方向的变化。例如:设备从纵向变为横向时,系统调用此 方法。我们应该使用此方法来响应GLSurfaceView容器的改变。

环境搭建

为了在Android应用程序中使用OpenGL ES绘制图形,必须要为他们创建一个视图容器。其中最直接或 者最常用的方式就是实现一个GLSurfaceView和一个GLSurfaceView.Renderer。GLSurfaceView是用 OpenGL绘制图形的视图容器,GLSurfaceView.Renderer控制在该视图内绘制的内容。 下面将讲解如何使用GLSurfaceView 和 GLSurfaceView.Renderer 在一个简单的应用程序的Activity上面 做一个最小的实现。

一:在Manifest中声明OpenGL ES使用

为了让你的应用程序能够使用OpenGL ES 2.0的API,你必须添加以下声明到manifest:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

如果你的应用程序需要使用纹理压缩,你还需要声明你的应用程序需要支持哪种压缩格式,以便他们安 装在兼容的设备上。

<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />

关于更多的纹理压缩格式的知识,可以到 developer.android.com/guide/topic… 做进一步的了解。

二:创建一个Activity 用于展示OpenGL ES图形

使用OpenGL ES的应用程序的Activity和其他应用程的Activity一样,不同的地方在于你设置的Activity的 布局。在许多使用OpenGL ES的app中,你可以添加TextView,Button和ListView,还可以添加 GLSurfaceView。 下面的代码展示了使用GLSurfaceView做为主视图的基本实现:

有2种使用方法,一是直接在xml里面用GLSurfaceView控件,二是直接用GLSurfaceView来当主视图

class OpenGLES20Activity : AppCompatActivity() {
    
    private lateinit var glView: GLSurfaceView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        glView = GLSurfaceView(this)
        setContentView(glView)
    }
}

三、创建GLSurfaceView对象

GLSurfaceView是一个特殊的View,通过这个View你可以绘制OpenGL图像。但是View本身没有做太多 的事情,主要的绘制是通过设置在View里面的GLSurfaceView.Renderer 来控制的。实际上,创建这个 对象的代码是很少的,你能会想尝试跳过extends的操作,只去创建一个没有被修改的GLSurfaceView 实例,但是不建议这样去做。因为在某些情况下,你需要扩展这个类来捕获触摸的事件,捕获触摸的事 件的方式会在后面的文章里面做介绍。 GLSurfaceView的基本代码很少,为了快速的实现,通常会在使用它的Activity中创建一个内部类来做实 现:

class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {

    private val renderer: MyGLRenderer

    init {
        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2)
        renderer = MyGLRenderer()
        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(renderer)
       renderMode = RENDERMODE_WHEN_DIRTY
    }


    private inner class MyGLRenderer : Renderer {
        override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {

        }

        override fun onSurfaceChanged(p0: GL10?, p1: Int, p2: Int) {

        }

        override fun onDrawFrame(p0: GL10?) {

        }

    }
}

你可以通过设置GLSurfaceView.RENDERMODE_WHEN_DIRTY来让你的GLSurfaceView监听到数据变化 的时候再去刷新,即修改GLSurfaceView的渲染模式。这个设置可以防止重绘GLSurfaceView,直到你 调用了requestRender(),这个设置在默写层面上来说,对你的APP是更有好处的。

四、创建一个Renderer类

实现了GLSurfaceView.Renderer 类才是真正算是开始能够在应用中使用OpenGL ES。这个类控制着与 它关联的GLSurfaceView 绘制的内容。在renderer 里面有三个方法能够被Android系统调用,以便知道 在GLSurfaceView绘制什么以及如何绘制

  • onSurfaceCreated() - 在View的OpenGL环境被创建的时候调用。
  • onDrawFrame() - 每一次View的重绘都会调用
  • onSurfaceChanged() - 如果视图的几何形状发生变化(例如,当设备的屏幕方向改变时), 则调用此方法。

下面是使用OpenGL ES 渲染器的基本实现,仅仅做的事情就是在GLSurfaceView绘制一个黑色背景。

private inner class MyGLRenderer : Renderer {
    override fun onSurfaceCreated(gl10: GL10?, config: EGLConfig?) {
        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
    }

    override fun onSurfaceChanged(gl10: GL10?, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height);
    }

    override fun onDrawFrame(gl10: GL10?) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
    }

}

总结

上述的内容就是基本的OpenGL ES基本的环境配置,本文的代码仅仅是创建一个简单的Android应用然 使用OpenGL展示一个黑板。虽然没有做其他更加有趣的事情,但是,通过创建这些类,你应该已经拥有了使用OpenGL绘制图形元素的基础了。 注:你可能很好奇为什么在使用OpenGL ES 2.0的API的时候会看到GL10的参数,因为这些方法签名2.0 API也可以使用