Android Studio NDK-OpenGL ES/EGL渲染

Android Studio NDK-OpenGL ES/EGL渲染
Android Studio NDK-OpenGL ES/EGL渲染

OpenGL EGL作為平臺冇関 API, 今程序冇視『Linux X Window』『Microsoft Windows』『Mac OS X Quatz』差異.用統壹接口同原生視窗聯接. 跨平臺API更易於移值. 所以OpenGL比DirectX更得人鐘意.

  1. 使用NDK
  2. 編譯OpenGL ES
  3. 布局OpenGL ES
  4. 先加入頭文檔
#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
  1. 冚辦爛EGL程式首先調用『eglGetDisplay()』, 得到『EGLDisplay』等同『原生視窗』, 『EGLDisplay』係整數索引.
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  1. 索引大於零即成功, 因為等於零失敗.
EGL_NO_DISPLAY 0失敗
  1. 初始EGL程式, 幷獲得『major』主版號 , 『minor』副版號
EGLint major,minor;

eglInitialize(display,&major,&minor)  ;

  1. 失敗返回EGL_FALSE, 查錯誤碼eglGetError()
EGL_BAD_DISPLAY 非有效EGLDisplay
EGL_NOT_INITALIZED 未能初始
  1. 穩『surface』渲染配置
EGLBoolean eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
  1. EglChooseConfig()函式參數
參數 簡介
EGLDisplay dpy 『原生視窗』索引
EGLint *attrib_list 指定屬性列表, 以EGL_NONE結屘
EGLConfig *configs 返回配置列表
EGLint config_size 指定配置列表長度
EGLint *num_config 返回配置長度
  1. 『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];
  1. 設定『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;  
  1. 據 attrib_array 返回最隹配置config
EGLint    config_number = 32;

EGLConfig config_array[32];

EGLConfig  config;// 配置

eglChooseConfig(display,attrib_array,config_array,config_number,&config_number);

  1. 匹配最佳配置
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;

}

}

  1. 生成渲染視窗
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
  1. eglCreateWindowSurface()函式參數
參數 簡介
EGLDisplay dpy 『原生視窗』索引
EGLConfig config 最佳配置
EGLNativeWindowType win SurfaceView
const EGLint *attrib_list 屬性列表
  1. 渲染視窗屬性
視窗屬性 描述
EGL_RENDER_BUFFER 渲染緩存 EGL_SINGLE_BUFFER『單緩存』EGL_BACK_BUFFER『雙緩存』
EGL_NONE 屬性列表以EGL_NONE結屘 0
  1. 屬性
attrib_array[0] = EGL_RENDER_BUFFER; attrib_array[1] = EGL_BACK_BUFFER;
attrib_array[2] = EGL_NONE;  
  1. 生成渲染視窗
surface_draw = eglCreateWindowSurface(display,config,nativeWindow,attrib_array);
  1. 獲得錯誤碼
錯誤碼EGLint error = eglGetError(); 簡介
EGL_BAD_MATCH 視窗唔匹配EGLConfig唔支持渲染
EGL_BAD_CONFIG 視窗唔匹配EGLConfig系統晤支持
EGL_BAD_NATIVE_WINDOW 原生視窗句柄冇效
EGL_BAD_ALLOC 冇法分配資源
  1. 關聯描述表, 将『EGLContext』『EGLSurface』與當前線程關聯, 『EGL』同『OpenGL』代碼需擺同壹綫程. 唔系eglSwapBuffers()返回
eglMakeCurrent(display,surface_draw,surface_draw,context);
  1. 『Native』層用『ANativeWindow 』蒞渲染.通過『Surface』得到『ANativeWindow』.
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface)
  1. Android 『java』層用『SurfaceView』蒞渲染, 提取『Surface』畀『Native』
SurfaceView surfaceView = (SurfaceView)findViewById(R.id.surface_view);
SurfaceHolder     surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
Surface             surface = surfaceHolder.getSurface();