【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 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM