http://www.imobilebbs.com/wordpress/?p=1889

Android OpenGL ES 相关的包主要定义在:

  • javax.microedition.khronos.opengles GL 绘图指令
  • javax.microedition.khronos.egl EGL 管理Display, surface等
  • android.opengl Android GL辅助类,连接OpenGL 与Android View,Activity
  • javax.nio Buffer类

其中GLSurfaceView 为android.opengl 包中核心类:

  • 起到连接OpenGL ES与Android 的View层次结构之间的桥梁作用。
  • 使得Open GL ES库适应于Anndroid系统的Activity生命周期。
  • 使得选择合适的Frame buffer像素格式变得容易。
  • 创建和管理单独绘图线程以达到平滑动画效果。
  • 提供了方便使用的调试工具来跟踪OpenGL ES函数调用以帮助检查错误。

使用过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一个可能的实现如下:

帮助
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 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.

帮助
1 public void setRenderer(GLSurfaceView.Renderer renderer)

GLSurfaceView.Renderer定义了一个统一图形绘制的接口,它定义了如下三个接口函数:

帮助
1 2 3 4 5 6 // 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)
  • onSurfaceCreated : 在这个方法中主要用来设置一些绘制时不常变化的参数,比如:背景色,是否打开 z-buffer等。
  • onDrawFrame: 定义实际的绘图操作。
  • onSurfaceChanged: 如果设备支持屏幕横向和纵向切换,这个方法将发生在横向<->纵向互换时。此时可以重新设置绘制的纵横比率。

如果有需要,也可以通过函数来修改GLSurfaceView一些缺省设置:

  • setDebugFlags(int) 设置Debug标志。
  • setEGLConfigChooser (boolean) 选择一个Config接近16bitRGB颜色模式,可以打开或关闭深度(Depth)Buffer ,缺省为RGB_565 并打开至少有16bit 的 depth Buffer.
  • setEGLConfigChooser(EGLConfigChooser) 选择自定义EGLConfigChooser。
  • setEGLConfigChooser(int, int, int, int, int, int) 指定red ,green, blue, alpha, depth ,stencil 支持的位数,缺省为RGB_565 ,16 bit depth buffer.

GLSurfaceView 缺省创建为RGB_565 颜色格式的Surface ,如果需要支持透明度,可以调用getHolder().setFormat(PixelFormat.TRANSLUCENT).

GLSurfaceView 的渲染模式有两种,一种是连续不断的更新屏幕,另一种为on-demand ,只有在调用requestRender() 在更新屏幕。 缺省为RENDERMODE_CONTINUOUSLY 持续刷新屏幕。

更多相关文章

  1. Android(安卓)4.4KitKat AudioFlinger 流程分析
  2. Android(安卓)7.1 系统 部分功能修改 汇总
  3. Android(安卓)应用启动时去掉应用图标
  4. android 串口jni 开发流程
  5. Android(安卓)自定义View
  6. Android中自定义checkbox样式
  7. Android(安卓)ApiDemos示例解析(166):Views->Layouts->TableLayo

随机推荐

  1. 利用Android多进程机制来分割组件
  2. Android 设备上实现串口的移植
  3. android代码混淆个人总结及踩坑
  4. Java: Swing中引入Android的NinePatch技
  5. Android NDK开发篇(六):Java与原生代码通
  6. Android R.java类的手动生成
  7. Android——AIDL基础实现demo以及原理探
  8. android图形系统详解五:Android绘制模式
  9. android 程序开发的插件化 模块化方法
  10. Android studio开发-第一个入门例子(十分