在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ GLSurfaceView
繪制線段 Line Segment
投影變換 Projection
繪制迷你太陽系
繪制一個球體
繪制三角形 Triangle
OpenGL 光照模型
三維坐標(biāo)系及坐標(biāo)變換初步
定義 3D 模型的前面和后面
繪制一個 20 面體
顏色 Color
Depth Buffer
材質(zhì)及光照示例
基本幾何圖形定義
關(guān)于EGL
導(dǎo)言
Viewing 和 Modeling(MODELVIEW) 變換
FrameBuffer
設(shè)置光照效果 Set Lighting
Viewport 變換
階段小結(jié)
繪制點 Point
OpenGL ES API 命名習(xí)慣
通用的矩陣變換指令
關(guān)于 OpenGL ES
創(chuàng)建實例應(yīng)用 OpenGLDemos 程序框架
OpenGL ES 管道(Pipeline)
GLSurfaceView

GLSurfaceView

Android OpenGL ES 相關(guān)的包主要定義在

  • 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 層次結(jié)構(gòu)之間的橋梁作用。
  • 使得 Open GL ES 庫適應(yīng)于 Anndroid 系統(tǒng)的 Activity 生命周期。
  • 使得選擇合適的 Frame buffer 像素格式變得容易。
  • 創(chuàng)建和管理單獨繪圖線程以達(dá)到平滑動畫效果。
  • 提供了方便使用的調(diào)試工具來跟蹤 OpenGL ES 函數(shù)調(diào)用以幫助檢查錯誤。

使用過 Java ME ,JSR 239 開發(fā)過 OpenGL ES 可以看到 Android 包javax.microedition.khronos.egl ,javax.microedition.khronos.opengles 和 JSR239 基本一致,因此理論上不使用 android.opengl 包中的類也可以開發(fā) Android 上 OpenGL ES 應(yīng)用,但此時就需要自己使用 EGL 來管理 Display,Context,Surfaces 的創(chuàng)建,釋放,捆綁,可以參見 Android OpenGL ES 開發(fā)教程(5):關(guān)于EGL

使用 EGL 實現(xiàn) GLSurfaceView 一個可能的實現(xiàn)如下:

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 ,并手工創(chuàng)建,銷毀 Display,Context,工作繁瑣。

使用 GLSurfaceView 內(nèi)部提供了上面類似的實現(xiàn),對于大部分應(yīng)用只需調(diào)用一個方法來設(shè)置 OpenGLView 用到的 GLSurfaceView.Renderer。

public void  setRenderer(GLSurfaceView.Renderer renderer)   

GLSurfaceView.Renderer 定義了一個統(tǒng)一圖形繪制的接口,它定義了如下三個接口函數(shù):

// 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:在這個方法中主要用來設(shè)置一些繪制時不常變化的參數(shù),比如:背景色,是否打開 z-buffer等。
  • onDrawFrame:定義實際的繪圖操作。
  • onSurfaceChanged:如果設(shè)備支持屏幕橫向和縱向切換,這個方法將發(fā)生在橫向<->縱向互換時。此時可以重新設(shè)置繪制的縱橫比率。

如果有需要,也可以通過函數(shù)來修改 GLSurfaceView 一些缺省設(shè)置:

  • setDebugFlags(int) 設(shè)置 Debug 標(biāo)志。
  • setEGLConfigChooser (boolean) 選擇一個 Config 接近 16bitRGB 顏色模式,可以打開或關(guān)閉深度(Depth)Buffer ,缺省為RGB_565 并打開至少有 16bit 的 depth Buffer。
  • setEGLConfigChooser(EGLConfigChooser) 選擇自定義 EGLConfigChooser。
  • setEGLConfigChooser(int, int, int, int, int, int) 指定 red ,green, blue, alpha, depth ,stencil 支持的位數(shù),缺省為 RGB_565 ,16 bit depth buffer。

GLSurfaceView 缺省創(chuàng)建為 RGB_565 顏色格式的 Surface,如果需要支持透明度,可以調(diào)用 getHolder().setFormat(PixelFormat.TRANSLUCENT)。

GLSurfaceView 的渲染模式有兩種,一種是連續(xù)不斷的更新屏幕,另一種為 on-demand ,只有在調(diào)用 requestRender() 在更新屏幕。 缺省為 RENDERMODE_CONTINUOUSLY 持續(xù)刷新屏幕。