构建 OpenGL ES 环境

如需在 Android 应用中使用 OpenGL ES 绘制图形,您必须为它们创建一个视图容器。其中一种比较直接的方式是同时实现 GLSurfaceViewGLSurfaceView.RendererGLSurfaceView 是使用 OpenGL 绘制的图形的视图容器,而 GLSurfaceView.Renderer 可控制该视图中绘制的图形。如需详细了解这些类,请参阅 OpenGL ES 开发者指南。

GLSurfaceView 只是将 OpenGL ES 图形整合到您应用中的其中一种方式。对于全屏或接近全屏的图形视图,这是一种合理的选择。希望将 OpenGL ES 图形整合到其布局的一小部分中的开发者应该了解下 TextureView。对于自己动手的真正开发者来说,也可以使用 SurfaceView 构建 OpenGL ES 视图,但这需要编写相当多的其他代码。

本课程介绍了如何在一个简单的应用 Activity 中完成 GLSurfaceViewGLSurfaceView.Renderer 的最低实现。

在清单中声明 OpenGL ES 的使用

为了让您的应用使用 OpenGL ES 2.0 API,您必须将以下声明添加到清单中:

    <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" />
    

如需详细了解纹理压缩格式,请参阅 OpenGL 开发者指南。

为 OpenGL ES 图形创建 Activity

使用 OpenGL ES 的 Android 应用的 Activity 与其他任何具有界面的应用相同。这种应用与其他应用的主要区别在于您在 Activity 的布局中添加了哪些内容。在很多应用中,您可以使用 TextViewButtonListView;而在使用 OpenGL ES 的应用中,您还可以添加一个 GLSurfaceView

以下代码示例展示了使用 GLSurfaceView 作为主要视图的 Activity 的最低实现:

Kotlin

    class OpenGLES20Activity : Activity() {

        private lateinit var gLView: GLSurfaceView

        public override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)

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

Java

    public class OpenGLES20Activity extends Activity {

        private GLSurfaceView gLView;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

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

注意:OpenGL ES 2.0 需要 Android 2.2(API 级别 8)或更高版本,因此请确保您的 Android 项目以该 API 或更高级别为目标。

构建 GLSurfaceView 对象

GLSurfaceView 是一种专用视图,您可以在其中绘制 OpenGL ES 图形。它本身并没有很大的作用。对象的实际绘制由您在此视图中设置的 GLSurfaceView.Renderer 控制。实际上,此对象的代码过于单薄,以至于您想要跳过对它的扩展,直接创建一个未经修改的 GLSurfaceView 实例,但请不要这样操作。您需要扩展此类才能捕获触摸事件,这在响应触摸事件课程中有所介绍。

GLSurfaceView 的基本代码很少,因此为了快速实现,通常只在使用它的 Activity 中创建一个内部类:

Kotlin

    import android.content.Context
    import android.opengl.GLSurfaceView

    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)
        }
    }
    

Java

    import android.content.Context;
    import android.opengl.GLSurfaceView;

    class MyGLSurfaceView extends GLSurfaceView {

        private final MyGLRenderer renderer;

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

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

            renderer = new MyGLRenderer();

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

GLSurfaceView 实现的另一种可选附加项是使用 GLSurfaceView.RENDERMODE_WHEN_DIRTY 设置将渲染模式设置为仅在绘制数据发生变化时绘制视图:

Kotlin

    // Render the view only when there is a change in the drawing data
    renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
    

Java

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

该设置可防止系统在您调用 requestRender() 之前重新绘制 GLSurfaceView 帧,这对于此示例应用而言更为高效。

构建渲染程序类

在使用 OpenGL ES 的应用中实现 GLSurfaceView.Renderer 类(或渲染程序)之后,事情就开始变得有趣起来。此类可控制在与之相关联的 GLSurfaceView 上绘制的内容。Android 系统会调用渲染程序中的以下三种方法来确定在 GLSurfaceView 上绘制什么内容以及如何绘制:

下面展示了 OpenGL ES 渲染程序一个非常基本的实现,即在 GLSurfaceView 上绘制一个黑色背景:

Kotlin

    import javax.microedition.khronos.egl.EGLConfig
    import javax.microedition.khronos.opengles.GL10

    import android.opengl.GLES20
    import android.opengl.GLSurfaceView

    class MyGLRenderer : GLSurfaceView.Renderer {

        override fun onSurfaceCreated(unused: GL10, config: EGLConfig) {
            // Set the background frame color
            GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
        }

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

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

Java

    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;

    import android.opengl.GLES20;
    import android.opengl.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 打造了一个显示黑屏的简单 Android 应用。虽然此代码并没有做任何有趣的事情,但通过创建这些类,您奠定了开始使用 OpenGL 绘制图形元素所需的基础。

注意:当您使用 OpengGL ES 2.0 API 时,您可能会好奇为何这些方法具有 GL10 参数。这些方法签名可以简单地重用于 2.0 API,以使 Android 框架代码更加简单。

如果您熟悉 OpenGL ES API,现在应该可以在应用中设置 OpenGL ES 环境并开始绘制图形。不过,如果您需要获取更多帮助以开始使用 OpenGL,请继续学习下一课来获取更多提示。