Android 第一个OpenGL ES程序
在你的Android应用中用OpenGL ES绘制图形,首先需要有一个容器,最直接的方法是实现GLSurfaceView
和 GLSurfaceView.Renderer
。
前者是一个放置图形的View容器,后者用来控制在这个View中如何进行绘制。
GLSurfaceView只是一种选择,比较适合于全屏绘制图形或者近似全屏绘制,其他可以选择的还有 TextureView
和SurfaceView
。
本文展示一个最基本的Android OpenGL ES绘制Demo。
1.在Manifest中添加声明
为了使用OpenGL ES 2.0 API,需要添加如下声明:
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
OpenGL ES 2.0 requires Android 2.2 (API Level 8) or higher,所以需要确认系统版本。
2.创建Activity
在Activity的布局中,需要加入GLSurfaceView来放置绘制的图形。
一个最简单的版本如下:
public class OpenGLES20 extends Activity { private GLSurfaceView mGLView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a GLSurfaceView instance and set it // as the ContentView for this Activity. mGLView = new MyGLSurfaceView(this); setContentView(mGLView); } }
3.创建GLSurfaceView
GLSurfaceView是一个特殊的组件,你可以在其中绘制OpenGL ES图形。
你需要扩展这个类,在它的构造方法中设置渲染器:
class MyGLSurfaceView extends GLSurfaceView { public MyGLSurfaceView(Context context){ super(context); // Set the Renderer for drawing on the GLSurfaceView setRenderer(new MyRenderer()); } }
如果使用OpenGL ES 2.0,还需要加一句声明:
// Create an OpenGL ES 2.0 context setEGLContextClientVersion(2);
还有一个可选的设置是,把渲染模式改为 GLSurfaceView.RENDERMODE_WHEN_DIRTY
,这样仅在你的数据有变化时重新进行渲染。
// Render the view only when there is a change in the drawing data setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
除非你调用requestRender(),这个设置会阻止帧被重画,有些情况下这样效率更高。
4.建立一个Renderer类
Renderer类(渲染器类),即 GLSurfaceView.Renderer
的实现类,它控制了与它相关联的 GLSurfaceView
上绘制什么。
其中有三个主要的回调方法:
onSurfaceCreated()
- Called once to set up the view's OpenGL ES environment.onDrawFrame()
- Called for each redraw of the view.onSurfaceChanged()
- Called if the geometry of the view changes, for example when the device's screen orientation changes.
一个简单的实现例子:
public class MyGL20Renderer implements GLSurfaceView.Renderer { public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Set the background frame color GLES20.glClearColor(0.5f, 0.5f, 0.5f, 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); } }
程序例子
一个简单的程序例子,并没有绘制什么,只是设置了背景色,为了展示方便,GLSurfaceView类和渲染器类都作为Acitivity的内部类写出。
首先在Manifest中加上声明:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloopengles" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <!-- Tell the system this app requires OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".HelloOpenGLESActivity" android:label="@string/title_activity_hello_open_gles" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
package com.example.helloopengles; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.app.Activity; import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.util.Log; public class HelloOpenGLESActivity extends Activity { private GLSurfaceView mGLView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a GLSurfaceView instance and set it // as the ContentView for this Activity. mGLView = new MyGLSurfaceView(this); setContentView(mGLView); } class MyGLSurfaceView extends GLSurfaceView { public MyGLSurfaceView(Context context) { super(context); try { // Create an OpenGL ES 2.0 context setEGLContextClientVersion(2); // Set the Renderer for drawing on the GLSurfaceView setRenderer(new MyRenderer()); // Render the view only when there is a change in the drawing // data setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // 注意上面语句的顺序,反了可能会出错 } catch (Exception e) { e.printStackTrace(); } } } public class MyRenderer implements GLSurfaceView.Renderer { public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Set the background frame color GLES20.glClearColor(0.5f, 0.5f, 0.5f, 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); } } }
参考资料
Training: Building an OpenGL ES Environment
http://developer.android.com/training/graphics/opengl/environment.html
OpenGL ES Developer Guide:
http://developer.android.com/guide/topics/graphics/opengl.html