为了在 Android 应用中使用 OpenGL ES 绘制图形,您必须为其创建一个 View 容器。一种更直接的方法是同时实现 GLSurfaceView
和 GLSurfaceView.Renderer
。GLSurfaceView
是用于绘制 OpenGL 图形的 View 容器,而 GLSurfaceView.Renderer
控制在该 View 中绘制的内容。有关这些类的更多信息,请参阅 OpenGL ES 开发者指南。
GLSurfaceView
只是将 OpenGL ES 图形集成到应用中的一种方法。对于全屏或接近全屏的图形视图,它是一个合理的选择。希望在其布局中一小部分区域集成 OpenGL ES 图形的开发者应查看 TextureView
。对于真正动手实践的开发者,也可以使用 SurfaceView
构建 OpenGL ES 视图,但这需要编写大量的额外代码。
本课程介绍如何在简单的应用 activity 中完成 GLSurfaceView
和 GLSurfaceView.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 的布局中放置的内容。在许多应用中,您可能使用 TextView
、Button
和 ListView
,但在使用 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
上绘制内容
onSurfaceCreated()
- 仅调用一次以设置 View 的 OpenGL ES 环境。onDrawFrame()
- 在每次重绘 View 时调用。onSurfaceChanged()
- 如果 View 的几何形状发生变化时调用,例如设备屏幕方向改变时。
这是一个非常基础的 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 入门方面的帮助,请继续学习下一课以获取更多提示。