为了在 Android 应用中使用 OpenGL ES 绘制图形,您必须为它们创建一个视图容器。最直接的方法之一是同时实现 GLSurfaceView 和 GLSurfaceView.Renderer。其中 GLSurfaceView 是用于 OpenGL 绘制图形的视图容器,而 GLSurfaceView.Renderer 则控制在该视图内绘制的内容。有关这些类的更多信息,请参阅 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 Level 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);
此设置可以防止 GLSurfaceView 帧在您调用 requestRender() 之前被重绘,这对本示例应用而言效率更高。
构建渲染器类
在使用 OpenGL ES 的应用中,GLSurfaceView.Renderer 类(或称渲染器)的实现是整个过程的核心。此类控制在该关联的 GLSurfaceView 上绘制的内容。渲染器中有三个方法由 Android 系统调用,以确定如何以及在 GLSurfaceView 上绘制什么:
onSurfaceCreated()- 调用一次,用于设置视图的 OpenGL ES 环境。onDrawFrame()- 每次重绘视图时调用。onSurfaceChanged()- 如果视图的几何形状发生变化(例如设备屏幕方向发生变化)时调用。
以下是一个最基本的 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 时还需要更多帮助,请继续学习后续课程以获取更多提示。