1. 程式人生 > >OpenGL ES之GLSurfaceView學習一:介紹

OpenGL ES之GLSurfaceView學習一:介紹

 GLSurfaceView是一個檢視,繼承至SurfaceView,它內嵌的surface專門負責OpenGL渲染。

        GLSurfaceView提供了下列特性:                 1> 管理一個surface,這個surface就是一塊特殊的記憶體,能直接排版到android的檢視view上。                 2> 管理一個EGL display,它能讓opengl把內容渲染到上述的surface上。                 3> 使用者自定義渲染器(render)。                 4> 讓渲染器在獨立的執行緒裡運作,和UI執行緒分離。                 5> 支援按需渲染(on-demand)和連續渲染(continuous)。                 6> 一些可選工具,如除錯。 使用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)方法就是一種相對簡單的操 作,例如下面的例子。          class MyGLSurfaceView extends GLSurfaceView {              private MyRenderer mMyRenderer;              public void start() {                  mMyRenderer = ...;                  setRenderer(mMyRenderer);              }              public boolean onKeyDown(int keyCode, KeyEvent event) {                  if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {                      queueEvent(new Runnable() {                          // 這個方法會在渲染執行緒裡被呼叫                          public void run() {                              mMyRenderer.handleDpadCenter();                          }});                      return true;                  }                  return super.onKeyDown(keyCode, event);              }          }         (注:如果在UI執行緒裡呼叫渲染器的方法,很容易收到“call to OpenGL ES API with no current context”的警告,典型的誤區就是在鍵盤或滑鼠事件方法裡直接呼叫opengl es的API,因為UI事件和渲染繪製在不同的執行緒裡。更甚者,這種情況下呼叫glDeleteBuffers這種釋放資源的方法,可能引起程式的崩潰, 因為UI執行緒想釋放它,渲染執行緒卻要使用它。)