Android OpenGL ES 相关的包主要定义在
其中GLSurfaceView 为android.opengl 包中核心类:
使用过Java ME ,JSR 239 开发过OpenGL ES可以看到 Android 包javax.microedition.khronos.egl ,javax.microedition.khronos.opengles 和JSR239 基本一致,因此理论上不使用android.opengl 包中的类也可以开发Android上OpenGL ES应用,但此时就需要自己使用EGL来管理Display,Context, Surfaces 的创建,释放,捆绑,可以参见Android OpenGL ES 开发教程(5):关于EGL 。
使用EGL 实现GLSurfaceView一个可能的实现如下:
class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { public GLSurfaceView(Context context) { super(context); mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU); } public void setRenderer(Renderer renderer) { mRenderer = renderer; } public void surfaceCreated(SurfaceHolder holder) { } public void surfaceDestroyed(SurfaceHolder holder) { running = false; try { thread.join(); } catch (InterruptedException e) { } thread = null; } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { synchronized(this){ mWidth = w; mHeight = h; thread = new Thread(this); thread.start(); } } public interface Renderer { void EGLCreate(SurfaceHolder holder); void EGLDestroy(); int Initialize(int width, int height); void DrawScene(int width, int height); } public void run() { synchronized(this) { mRenderer.EGLCreate(mHolder); mRenderer.Initialize(mWidth, mHeight); running=true; while (running) { mRenderer.DrawScene(mWidth, mHeight); } mRenderer.EGLDestroy(); } } private SurfaceHolder mHolder; private Thread thread; private boolean running; private Renderer mRenderer; private int mWidth; private int mHeight; } class GLRenderer implements GLSurfaceView.Renderer { public GLRenderer() { } public int Initialize(int width, int height){ gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f); return 1; } public void DrawScene(int width, int height){ gl.glClear(GL10.GL_COLOR_BUFFER_BIT); egl.eglSwapBuffers(eglDisplay, eglSurface); } public void EGLCreate(SurfaceHolder holder){ int[] num_config = new int[1]; EGLConfig[] configs = new EGLConfig[1]; int[] configSpec = { EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8, EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, EGL10.EGL_NONE }; this.egl = (EGL10) EGLContext.getEGL(); eglDisplay = this.egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); this.egl.eglInitialize(eglDisplay, null); this.egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, num_config); eglConfig = configs[0]; eglContext = this.egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, null); eglSurface = this.egl.eglCreateWindowSurface(eglDisplay, eglConfig, holder, null); this.egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); gl = (GL10)eglContext.getGL(); } public void EGLDestroy(){ if (eglSurface != null) { egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); egl.eglDestroySurface(eglDisplay, eglSurface); eglSurface = null; } if (eglContext != null) { egl.eglDestroyContext(eglDisplay, eglContext); eglContext = null; } if (eglDisplay != null) { egl.eglTerminate(eglDisplay); eglDisplay = null; } } private EGL10 egl; private GL10 gl; private EGLDisplay eglDisplay; private EGLConfig eglConfig; private EGLContext eglContext; private EGLSurface eglSurface; }
可以看到需要派生SurfaceView ,并手工创建,销毁Display,Context ,工作繁琐。
使用GLSurfaceView 内部提供了上面类似的实现,对于大部分应用只需调用一个方法来设置OpenGLView用到的GLSurfaceView.Renderer.
public void setRenderer(GLSurfaceView.Renderer renderer)
GLSurfaceView.Renderer定义了一个统一图形绘制的接口,它定义了如下三个接口函数:
// Called when the surface is created or recreated. public void onSurfaceCreated(GL10 gl, EGLConfig config) // Called to draw the current frame. public void onDrawFrame(GL10 gl) // Called when the surface changed size. public void onSurfaceChanged(GL10 gl, int width, int height)
如果有需要,也可以通过函数来修改GLSurfaceView一些缺省设置:
GLSurfaceView 缺省创建为RGB_565 颜色格式的Surface ,如果需要支持透明度,可以调用getHolder().setFormat(PixelFormat.TRANSLUCENT).
GLSurfaceView 的渲染模式有两种,一种是连续不断的更新屏幕,另一种为on-demand ,只有在调用requestRender() 在更新屏幕。 缺省为RENDERMODE_CONTINUOUSLY 持续刷新屏幕。