OpenGL EGL作為平臺冇関 API, 今程序冇視『Linux X Window』『Microsoft Windows』『Mac OS X Quatz』差異.用統壹接口同原生視窗聯接. 跨平臺API更易於移值. 所以OpenGL比DirectX更得人鐘意.
- 使用NDK
- 編譯OpenGL ES
- 布局OpenGL ES
- 先加入頭文檔
#include <GLES/gl.h> | 標準OpenGL頭文檔 |
#include <GLES/glext.h> | OpenGL實用架餐庫 |
#include <EGL/egl.h> | EGL庫 |
#include <EGL/eglext.h> | EGL架餐庫 |
#include <android/native_window_jni.h> | 原生視窗庫ANativeWindow |
- 冚辦爛EGL程式首先調用『eglGetDisplay()』, 得到『EGLDisplay』等同『原生視窗』, 『EGLDisplay』係整數索引.
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
- 索引大於零即成功, 因為等於零失敗.
EGL_NO_DISPLAY | 0失敗 |
- 初始EGL程式, 幷獲得『major』主版號 , 『minor』副版號
EGLint major,minor;
eglInitialize(display,&major,&minor) ; |
- 失敗返回EGL_FALSE, 查錯誤碼eglGetError()
EGL_BAD_DISPLAY | 非有效EGLDisplay |
EGL_NOT_INITALIZED | 未能初始 |
- 穩『surface』渲染配置
EGLBoolean eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); |
- EglChooseConfig()函式參數
參數 | 簡介 |
EGLDisplay dpy | 『原生視窗』索引 |
EGLint *attrib_list | 指定屬性列表, 以EGL_NONE結屘 |
EGLConfig *configs | 返回配置列表 |
EGLint config_size | 指定配置列表長度 |
EGLint *num_config | 返回配置長度 |
- 『EGLConfig』屬性
屬性 | 描述 | 值 |
EGL_SURFACE_TYPE | EGL渲染表面類型 | EGL_WINDOW_BIT |
EGL_RENDERABLE_TYPE | OpenGL版本 | EGL_OPENGL_ES_BIT |
EGL_RED_SIZE | 紅色量位 | 8Bit |
EGL_GREEN_SIZE | 綠色量位 | 8Bit |
EGL_BLUE_SIZE | 藍色量位 | 8Bit |
EGL_ALPHA_SIZE | 透明量位 | 8Bit |
EGL_DEPTH_SIZE | 深度量位 | 16Bit |
EGL_NONE | 屬性列表以EGL_NONE結屘 | 0 |
屬性列表
EGLint attrib_array[32]; |
- 設定『EGLConfig』屬性
attrib_array[0] = EGL_SURFACE_TYPE; | attrib_array[1] = EGL_WINDOW_BIT; |
attrib_array[2] = EGL_RENDERABLE_TYPE; | attrib_array[3] = EGL_OPENGL_ES_BIT; |
attrib_array[4] = EGL_RED_SIZE; | attrib_array[5] = 8; |
attrib_array[6] = EGL_GREEN_SIZE; | attrib_array[7] = 8, |
attrib_array[8] = EGL_BLUE_SIZE; | attrib_array[9] = 8; |
attrib_array[10] = EGL_ALPHA_SIZE; | attrib_array[11] = 8; |
attrib_array[12] = EGL_DEPTH_SIZE; | attrib_array[13] = 16; |
attrib_array[14] = EGL_NONE; |
- 據 attrib_array 返回最隹配置config
EGLint config_number = 32;
EGLConfig config_array[32]; EGLConfig config;// 配置 eglChooseConfig(display,attrib_array,config_array,config_number,&config_number); |
- 匹配最佳配置
for(int i=0;i<config_number;++i) {
eglGetConfigAttrib(openGL->display, config_array[i],EGL_RED_SIZE, &red); eglGetConfigAttrib(openGL->display, config_array[i],EGL_GREEN_SIZE, &green); eglGetConfigAttrib(openGL->display, config_array[i],EGL_BLUE_SIZE, &blue); eglGetConfigAttrib(openGL->display, config_array[i],EGL_ALPHA_SIZE, &alpha); eglGetConfigAttrib(openGL->display, config_array[i],EGL_DEPTH_SIZE, &depth); if( red == 8 && green == 8 && blue == 8 && alpha == 8 && depth == 16){ openGL->config = config_array[i];// 最佳配置 break; } } |
- 生成渲染視窗
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); |
- eglCreateWindowSurface()函式參數
參數 | 簡介 |
EGLDisplay dpy | 『原生視窗』索引 |
EGLConfig config | 最佳配置 |
EGLNativeWindowType win | SurfaceView |
const EGLint *attrib_list | 屬性列表 |
- 渲染視窗屬性
視窗屬性 | 描述 | 值 |
EGL_RENDER_BUFFER | 渲染緩存 | EGL_SINGLE_BUFFER『單緩存』EGL_BACK_BUFFER『雙緩存』 |
EGL_NONE | 屬性列表以EGL_NONE結屘 | 0 |
- 屬性
attrib_array[0] = EGL_RENDER_BUFFER; | attrib_array[1] = EGL_BACK_BUFFER; |
attrib_array[2] = EGL_NONE; |
- 生成渲染視窗
surface_draw = eglCreateWindowSurface(display,config,nativeWindow,attrib_array); |
- 獲得錯誤碼
錯誤碼EGLint error = eglGetError(); | 簡介 |
EGL_BAD_MATCH | 視窗唔匹配EGLConfig唔支持渲染 |
EGL_BAD_CONFIG | 視窗唔匹配EGLConfig系統晤支持 |
EGL_BAD_NATIVE_WINDOW | 原生視窗句柄冇效 |
EGL_BAD_ALLOC | 冇法分配資源 |
- 關聯描述表, 将『EGLContext』『EGLSurface』與當前線程關聯, 『EGL』同『OpenGL』代碼需擺同壹綫程. 唔系eglSwapBuffers()返回
eglMakeCurrent(display,surface_draw,surface_draw,context); |
- 『Native』層用『ANativeWindow 』蒞渲染.通過『Surface』得到『ANativeWindow』.
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) |
- Android 『java』層用『SurfaceView』蒞渲染, 提取『Surface』畀『Native』
SurfaceView surfaceView = (SurfaceView)findViewById(R.id.surface_view); |
SurfaceHolder surfaceHolder = surfaceView.getHolder(); |
surfaceHolder.addCallback(this); |
Surface surface = surfaceHolder.getSurface(); |