zoukankan      html  css  js  c++  java
  • 【Android】GLSurfaceView

    An implementation of SurfaceView that uses the dedicated surface for displaying OpenGL rendering.

    A GLSurfaceView provides the following features:

    • Manages a surface, which is a special piece of memory that can be composited into the Android view system.
    • Manages an EGL display, which enables OpenGL to render into a surface.
    • Accepts a user-provided Renderer object that does the actual rendering.
    • Renders on a dedicated thread to decouple rendering performance from the UI thread.
    • Supports both on-demand and continuous rendering.
    • Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.

    SurfaceView的实现,使用OpenGL进行渲染。它提供以下特征:

    1)管理一个“界面”,是一块内存,可以被组合进入Android的界面系统;

    2)管理EGL显示,可以允许OpenGL渲染;

    3)接受用于提供的渲染器进行渲染;

    4)独立开辟线程进行渲染;

    5)提供持续的渲染;

    总之一句话,这个类很适合做渲染工作。

    使用GLSurfaceView
            通常会继承GLSurfaceView,并重载一些和用户输入事件有关的方法。如果你不需要重载事件方法,GLSurfaceView也可以直接使用,你可以使用set方法来为该类提供自定义的行为。例如,GLSurfaceView的渲染被委托给渲染器在独立的渲染线程里进行,这一点和普通视图不一样,setRenderer(Renderer)设置渲染器。
     
    初始化GLSurfaceView
            初始化过程其实仅需要你使用setRenderer(Renderer)设置一个渲染器(render)。当然,你也可以修改GLSurfaceView一些默认配置。
    * setDebugFlags(int)
    * setEGLConfigChooser(boolean)
    * setEGLConfigChooser(EGLConfigChooser)
    * setEGLConfigChooser(int, int, int, int, int, int)
    * setGLWrapper(GLWrapper) 
     
    定制android.view.Surface
            GLSurfaceView默认会创建像素格式为PixelFormat.RGB_565的surface。如果需要透明效果,调用getHolder().setFormat(PixelFormat.TRANSLUCENT)。透明(TRANSLUCENT)的surface的像素格式都是32位,每个色彩单元都是8位深度,像素格式是设备相关的,这意味着它可能是ARGB、RGBA或其它。
     
    选择EGL配置
            Android设备往往支持多种EGL配置,可以使用不同数目的通道(channel),也可以指定每个通道具有不同数目的位(bits)深度。因此,在渲染器工作之前就应该指定EGL的配置。GLSurfaceView默认EGL配置的像素格式为RGB_656,16位的深度缓存(depth buffer),默认不开启遮罩缓存(stencil buffer)。
            如果你要选择不同的EGL配置,请使用setEGLConfigChooser方法中的一种。
            
    调试行为
            你可以调用调试方法setDebugFlags(int)或setGLWrapper(GLSurfaceView.GLWrapper)来自定义GLSurfaceView一些行为。在setRenderer方法之前或之后都可以调用调试方法,不过最好是在之前调用,这样它们能立即生效。
            
    设置渲染器
            总之,你必须调用setRenderer(GLSurfaceView.Renderer)来注册一个GLSurfaceView.Renderer渲染器。渲染器负责真正的GL渲染工作。
            
    渲染模式
            渲染器设定之后,你可以使用setRenderMode(int)指定渲染模式是按需(on demand)还是连续(continuous)。默认是连续渲染。
            
    Activity生命周期
            Activity窗口暂停(pause)或恢复(resume)时,GLSurfaceView都会收到通知,此时它的onPause方法和onResume方法应该被调用。这样做是为了让GLSurfaceView暂停或恢复它的渲染线程,以便它及时释放或重建OpenGL的资源。
     
    事件处理
            为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法。但是由于GLSurfaceView是多线程操作,所以需要一些特殊的处理。由于渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯。queueEvent(Runnable)方法就是一种相对简单的操作,例如下面的例子
     1 class MyGLSurfaceView extends GLSurfaceView {
     2 
     3      private MyRenderer mMyRenderer;
     4 
     5      public void start() {
     6          mMyRenderer = ...;
     7          setRenderer(mMyRenderer);
     8      }
     9 
    10      public boolean onKeyDown(int keyCode, KeyEvent event) {
    11          if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    12              queueEvent(new Runnable() {
    13                  // This method will be called on the rendering
    14                  // thread:
    15                  public void run() {
    16                      mMyRenderer.handleDpadCenter();
    17                  }});
    18              return true;
    19          }
    20          return super.onKeyDown(keyCode, event);
    21      }
    22  }

    示例代码:

     1 import javax.microedition.khronos.egl.EGLConfig;
     2 import javax.microedition.khronos.opengles.GL10;
     3 import android.app.Activity;
     4 import android.opengl.GLSurfaceView;
     5 import android.os.Bundle;
     6 public class ClearActivity extends Activity {
     7   @Override
     8   protected void onCreate(Bundle savedInstanceState) {
     9     super.onCreate(savedInstanceState);
    10     mGLView = new GLSurfaceView(this);
    11     mGLView.setRenderer(new ClearRenderer());
    12     setContentView(mGLView);
    13   }
    14   @Override
    15   protected void onPause() {
    16     super.onPause();
    17     mGLView.onPause();
    18   }
    19   @Override
    20   protected void onResume() {
    21     super.onResume();
    22     mGLView.onResume();
    23   }
    24   private GLSurfaceView mGLView;
    25   }
    26   class ClearRenderer implements GLSurfaceView.Renderer {
    27     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    28       // Do nothing special.
    29     }
    30     public void onSurfaceChanged(GL10 gl, int w, int h) {
    31       gl.glViewport(0, 0, w, h);
    32     }
    33     public void onDrawFrame(GL10 gl) {
    34     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    35   }
    36 }

    这个程序功能很简单,每帧绘制时将屏幕设置成黑色。但它是一个完整的工作在Activity 生命周期中的 OpenGL 程序。当 activity 暂停时,它暂停渲染;当activity 继续时,它继续渲染。可以将这个程序用作非交互式的 demo 程序。可以在 ClearRenderer.onDrawFrame() 接口中增加 OpenGL 调用做很多的绘制。

    GLSurfaceView.Render 接口有三个方法:

    • onSurfaceCreated():该方法在渲染开始前调用,OpenGL ES 的绘制上下文被重建时也会被调用。当 activity 暂停时绘制上下文会丢失,当 activity 继续时,绘制上下文会被重建。另外,创建长期存在的 OpenGL 资源(如texture)往往也在这里进行。
    • onSurfaceChanged():当 surface 的尺寸发生改变时该方法被调用。往往在这里设置 viewport。若你的 camera 是固定的,也可以在这里设置 camera。
    • onDrawFrame():每帧都通过该方法进行绘制。绘制时通常先调用 glClear 函数来清空 framebuffer,然后在调用 OpenGL ES 的起它的接口进行绘制。

    若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件。下面有个例子:

     1 import javax.microedition.khronos.egl.EGLConfig;
     2 import javax.microedition.khronos.opengles.GL10;
     3 import android.app.Activity;
     4 import android.content.Context;
     5 import android.opengl.GLSurfaceView;
     6 import android.os.Bundle;
     7 import android.view.MotionEvent;
     8 public class ClearActivity extends Activity {
     9   @Override
    10   protected void onCreate(Bundle savedInstanceState) {
    11     super.onCreate(savedInstanceState);
    12     mGLView = new ClearGLSurfaceView(this);
    13     setContentView(mGLView);
    14   }
    15   @Override
    16   protected void onPause() {
    17     super.onPause();
    18     mGLView.onPause();
    19   }
    20   @Override
    21   protected void onResume() {
    22     super.onResume();
    23     mGLView.onResume();
    24   }
    25   private GLSurfaceView mGLView;
    26   }
    27   class ClearGLSurfaceView extends GLSurfaceView {
    28     public ClearGLSurfaceView(Context context) {
    29       super(context);
    30       mRenderer = new ClearRenderer();
    31       setRenderer(mRenderer);
    32     }
    33     public boolean onTouchEvent(final MotionEvent event) {
    34       queueEvent(new Runnable(){
    35         public void run() {
    36           mRenderer.setColor(event.getX() / getWidth(),
    37           event.getY() / getHeight(), 1.0f);
    38         }});
    39       return true;
    40     }
    41     ClearRenderer mRenderer;
    42 }
    43 class ClearRenderer implements GLSurfaceView.Renderer {
    44   public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    45     // Do nothing special.
    46   }
    47   public void onSurfaceChanged(GL10 gl, int w, int h) {
    48     gl.glViewport(0, 0, w, h);
    49   }
    50   public void onDrawFrame(GL10 gl) {
    51     gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
    52     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    53   }
    54   public void setColor(float r, float g, float b) {
    55     mRed = r;
    56     mGreen = g;
    57     mBlue = b;
    58   }
    59   private float mRed;
    60   private float mGreen;
    61   private float mBlue;
    62 }
    63  

    博客整理自:http://blog.sina.com.cn/s/blog_972577b3010100l1.html 

  • 相关阅读:
    python gui
    20189217 2018-2019-2 《密码与安全新技术专题》第11周作业
    20189217 2018-2019-2 本地音乐播放器cocoMusic 代码分析
    20189217 2018-2019-2 《移动平台开发实践》第12周学习总结
    20189217 2018-2019-2 《移动平台开发实践》课程总结
    20189217 2018-2019-2 《移动平台开发实践》第11周学习总结
    20189217 2018-2019-2 《密码与安全新技术专题》第9周作业
    20189217 2018-2019-2 《移动平台开发实践》第10周学习总结
    20189217 2018-2019-2 《移动平台开发实践》第9周学习总结
    AES
  • 原文地址:https://www.cnblogs.com/lqminn/p/2732513.html
Copyright © 2011-2022 走看看