Android OpenGL ES 开发教程(6):GLSurfaceView

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

[java]  view plain copy print ?
  1. class GLSurfaceView extends SurfaceView  
  2.  implements SurfaceHolder.Callback, Runnable {  
  3.  public GLSurfaceView(Context context) {  
  4.  super(context);  
  5.  mHolder = getHolder();  
  6.  mHolder.addCallback(this);  
  7.  mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);  
  8.  }  
  9.    
  10.  public void setRenderer(Renderer renderer) {  
  11.  mRenderer = renderer;  
  12.  }  
  13.    
  14.  public void surfaceCreated(SurfaceHolder holder) {  
  15.  }  
  16.    
  17.  public void surfaceDestroyed(SurfaceHolder holder) {  
  18.  running = false;  
  19.  try {  
  20.  thread.join();  
  21.  } catch (InterruptedException e) {  
  22.  }  
  23.  thread = null;  
  24.  }  
  25.    
  26.  public void surfaceChanged(SurfaceHolder holder,  
  27.  int format, int w, int h) {  
  28.  synchronized(this){  
  29.  mWidth = w;  
  30.  mHeight = h;  
  31.  thread = new Thread(this);  
  32.  thread.start();  
  33.  }  
  34.  }  
  35.    
  36.  public interface Renderer {  
  37.  void EGLCreate(SurfaceHolder holder);  
  38.  void EGLDestroy();  
  39.  int Initialize(int width, int height);  
  40.  void DrawScene(int width, int height);  
  41.  }  
  42.    
  43.  public void run() {  
  44.  synchronized(this) {  
  45.  mRenderer.EGLCreate(mHolder);  
  46.  mRenderer.Initialize(mWidth, mHeight);  
  47.    
  48.  running=true;  
  49.  while (running) {  
  50.  mRenderer.DrawScene(mWidth, mHeight);  
  51.  }  
  52.    
  53.  mRenderer.EGLDestroy();  
  54.  }  
  55.  }  
  56.    
  57.  private SurfaceHolder mHolder;  
  58.  private Thread thread;  
  59.  private boolean running;  
  60.  private Renderer mRenderer;  
  61.  private int mWidth;  
  62.  private int mHeight;  
  63.    
  64. }  
  65.    
  66. class GLRenderer implements GLSurfaceView.Renderer {  
  67.  public GLRenderer() {  
  68.  }  
  69.    
  70.  public int Initialize(int width, int height){  
  71.  gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);  
  72.    
  73.  return 1;  
  74.  }  
  75.    
  76.  public void DrawScene(int width, int height){  
  77.  gl.glClear(GL10.GL_COLOR_BUFFER_BIT);  
  78.    
  79.  egl.eglSwapBuffers(eglDisplay, eglSurface);  
  80.  }  
  81.    
  82.  public void EGLCreate(SurfaceHolder holder){  
  83.  int[] num_config = new int[1];  
  84.  EGLConfig[] configs = new EGLConfig[1];  
  85.  int[] configSpec = {  
  86.  EGL10.EGL_RED_SIZE,            8,  
  87.  EGL10.EGL_GREEN_SIZE,        8,  
  88.  EGL10.EGL_BLUE_SIZE,        8,  
  89.    
  90.  EGL10.EGL_SURFACE_TYPE,     EGL10.EGL_WINDOW_BIT,  
  91.  EGL10.EGL_NONE  
  92.  };  
  93.    
  94.  this.egl = (EGL10) EGLContext.getEGL();  
  95.    
  96.  eglDisplay = this.egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);  
  97.  this.egl.eglInitialize(eglDisplay, null);  
  98.    
  99.  this.egl.eglChooseConfig(eglDisplay, configSpec,  
  100.  configs, 1, num_config);  
  101.    
  102.  eglConfig = configs[0];  
  103.  eglContext = this.egl.eglCreateContext(eglDisplay, eglConfig,  
  104.  EGL10.EGL_NO_CONTEXT, null);  
  105.    
  106.  eglSurface = this.egl.eglCreateWindowSurface(eglDisplay,  
  107.  eglConfig, holder, null);  
  108.    
  109.  this.egl.eglMakeCurrent(eglDisplay, eglSurface,  
  110.  eglSurface, eglContext);  
  111.    
  112.  gl = (GL10)eglContext.getGL();  
  113.  }  
  114.    
  115.  public void EGLDestroy(){  
  116.  if (eglSurface != null) {  
  117.  egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,  
  118.  EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);  
  119.  egl.eglDestroySurface(eglDisplay, eglSurface);  
  120.  eglSurface = null;  
  121.  }  
  122.  if (eglContext != null) {  
  123.  egl.eglDestroyContext(eglDisplay, eglContext);  
  124.  eglContext = null;  
  125.  }  
  126.  if (eglDisplay != null) {  
  127.  egl.eglTerminate(eglDisplay);  
  128.  eglDisplay = null;  
  129.  }  
  130.  }  
  131.    
  132.  private EGL10 egl;  
  133.  private GL10 gl;  
  134.  private EGLDisplay eglDisplay;  
  135.  private EGLConfig  eglConfig;  
  136.  private EGLContext eglContext;  
  137.  private EGLSurface eglSurface;  
  138. }  

可以看到需要派生SurfaceView ,并手工创建,销毁Display,Context ,工作繁琐。

使用GLSurfaceView 内部提供了上面类似的实现,对于大部分应用只需调用一个方法来设置OpenGLView用到的GLSurfaceView.Renderer.

[java]  view plain copy print ?
  1. public void  setRenderer(GLSurfaceView.Renderer renderer)  

 

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

[java]  view plain copy print ?
  1. // Called when the surface is created or recreated.  
  2. public void onSurfaceCreated(GL10 gl, EGLConfig config)  
  3. // Called to draw the current frame.  
  4. public void onDrawFrame(GL10 gl)  
  5. // Called when the surface changed size.  
  6. 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 持续刷新屏幕。


  • 原文出处:http://blog.csdn.net/mapdigit/article/details/7567094

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值