构建 OpenGL ES 环境

为了在 Android 应用中使用 OpenGL ES 绘制图形,您必须为其创建一个 View 容器。一种更直接的方法是同时实现 GLSurfaceViewGLSurfaceView.RendererGLSurfaceView 是用于绘制 OpenGL 图形的 View 容器,而 GLSurfaceView.Renderer 控制在该 View 中绘制的内容。有关这些类的更多信息,请参阅 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 图形的 View。它本身的功能不多。对象的实际绘制是在您为此 View 设置的 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);

此设置会阻止 GLSurfaceView 帧被重绘,直到您调用 requestRender()。对于此示例应用而言,这种方式更高效。

构建渲染器类

在使用 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);
    }
}

就这样!上面的代码示例创建了一个简单的 Android 应用,使用 OpenGL 显示一个黑色屏幕。虽然这段代码没有做任何非常有趣的事情,但通过创建这些类,您已经为开始使用 OpenGL 绘制图形元素奠定了基础。

注意:当您使用 OpenGL ES 2.0 API 时,您可能想知道为什么这些方法有一个 GL10 参数。这些方法签名只是为了保持 Android 框架代码更简单而为 2.0 API 重复使用。

如果您熟悉 OpenGL ES API,现在应该能够在您的应用中设置 OpenGL ES 环境并开始绘制图形。但是,如果您需要更多关于 OpenGL 入门方面的帮助,请继续学习下一课以获取更多提示。