Android OPENGL 第二天:通過NDK實(shí)現(xiàn)GL的繪制(基礎(chǔ))

????從今天開始我學(xué)習(xí)的GL知識都通過使用C++進(jìn)行開發(fā),需要用到安卓的NDK

????今天先封裝一個(gè)我們自己的工具類

????C++的語法還是比較難理解,可能是我經(jīng)常用Java習(xí)慣了,突然要我去做C++,還是有一點(diǎn)難為人,ok,開始學(xué)習(xí)

? ? 首先GL的繪制和使用需要用到下面的幾個(gè)重要工具:

? ??EGLDisplay:這個(gè)是GL現(xiàn)實(shí)的顯存,用來連接顯示器的

????EGLSurface:這個(gè)是buffer的緩沖區(qū)

????EGLConfig:這個(gè)就從字面上可以理解為GL的配置信息

????EGLContext:因?yàn)樾枰玫脚c顯存的buffer交換,需要共享上下文,這個(gè)還是很重要的。

? ? 我們首先做一個(gè)工具類,就叫EGLHelper好了:

class WlEglHelper {

public:

????EGLDisplay? mEglDisplay;

? ? EGLSurface? mEglSurface;

? ? EGLConfig? mEglConfig;

? ? EGLContext mEglContext;

}

那定義好了基礎(chǔ)變量,還得定義一個(gè)方法對GL進(jìn)行初始化,那就命名?initEgl()好了,但是你還得存入一個(gè)EGLNativeWindowType 的參數(shù),因?yàn)檫@個(gè)是為了讓gl展示的window的類型,因?yàn)楝F(xiàn)實(shí)的類型不只是這種,可能還有其他的類型,不過現(xiàn)在就用到了這種類型

? ? 那現(xiàn)在就寫這個(gè)方法的邏輯:

思路:首先你得獲取他的展示容器,GL的容器的ID的名稱是:

EGL_DEFAULT_DISPLAY

那然后就是判斷你有沒有獲取容器成功咯!所以就通過判斷

if(mEglDisplay ==EGL_NO_DISPLAY){

LOGE("eglGetDisplay error");

? ? return -1;

}

然后接下來就是對GL進(jìn)行初始化,并且進(jìn)行判斷是否成功:

EGLint *version =new EGLint[2];

if(!eglInitialize(mEglDisplay, &version[0], &version[1])){

LOGE("eglInitialize error");

? ? return -1;

}

然后接下來就聲明gl的一些基本屬性值:

const EGLint attribs[] = {

EGL_RED_SIZE, 8,

? ? ? ? EGL_GREEN_SIZE, 8,

? ? ? ? EGL_BLUE_SIZE, 8,

? ? ? ? EGL_ALPHA_SIZE, 8,

? ? ? ? EGL_DEPTH_SIZE, 8,

? ? ? ? EGL_STENCIL_SIZE, 8,

? ? ? ? EGL_RENDERABLE_TYPE,

? ? ? ? EGL_OPENGL_ES2_BIT,

? ? ? ? EGL_NONE

};

這幾個(gè)變量的意義我說明一下:

EGL_RED_SIZE, 8

的意思是RED這個(gè)在顏色緩沖區(qū)紅色分量的位數(shù)為8,

那后面的EGL_GREEN_SIZE,EGL_BLUE_SIZE就是綠色和藍(lán)色的在顏色緩沖區(qū)的位數(shù),后面的透明值(EGL_ALPHA_SIZE)和深度緩沖區(qū)(EGL_DEPTH_SIZE)的位數(shù),模板緩沖區(qū)(EGL_STENCIL_SIZE)的位數(shù),支持渲染的接口(EGL_RENDERABLE_TYPE),那最后的那個(gè)是做什么的呢?最后那個(gè)是用來做結(jié)束語的,就是標(biāo)志著這個(gè)數(shù)組結(jié)束了。

然后就是通過eglChooseConfig來進(jìn)行對GL的配置了

EGLint num_config;

if(!eglChooseConfig(mEglDisplay, attribs, NULL, 1, &num_config)){

LOGE("eglChooseConfig? error 1");

? ? return -1;

}

然后就是要獲取上下文,這個(gè)的配置項(xiàng)的內(nèi)容是:

int attrib_list[] = {

EGL_CONTEXT_CLIENT_VERSION, 2,

? ? ? ? EGL_NONE

};

這個(gè)配置就比較簡單了,第一個(gè)參數(shù)是GL上下文的客戶端版本號,然后后面那個(gè)就不用說了,

然后實(shí)現(xiàn)的方法是:

mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list);

if(mEglContext ==EGL_NO_CONTEXT){

LOGE("eglCreateContext? error");

? ? return -1;

}

然后接下來就是創(chuàng)建顯示的界面了:

mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);

if(mEglSurface ==EGL_NO_SURFACE){

LOGE("eglCreateWindowSurface? error");

? ? return -1;

}

然后你做完了GL的對應(yīng)的配置,你要如何啟動(dòng)他們呢?我們目前有上下文,有顯示界面,有配置項(xiàng),有顯示模板,但是想要他們組合在一起,并且實(shí)現(xiàn)上下問的切換,需要用到一個(gè)很重要的方法:

if(!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)){

LOGE("eglMakeCurrent? error");

? ? return -1;

}

就是makeCurrent(),這個(gè)方法是用來對上下文進(jìn)行切換,OPENGL才可以起作用的,這個(gè)還是蠻重要的。

那做完了這些,那是不是還得讓他們不停的切換,這個(gè)切換是與顯存進(jìn)行buffer的交換,那還是得使用eglSwapBuffers()進(jìn)行display和surface進(jìn)行buffer的交換:

if(mEglDisplay !=EGL_NO_DISPLAY &&mEglSurface !=EGL_NO_SURFACE){

if(eglSwapBuffers(mEglDisplay, mEglSurface))

return 0;

? }

}

return -1;

好了,我們來總結(jié)一下實(shí)現(xiàn)思路:GL其實(shí)就是顯卡暴露出來的一系列的接口,是可以通過他直接操作顯卡進(jìn)行顯示你要的圖像,然后顯卡一般是不處理視頻的,只處理圖片,然后這個(gè)在開發(fā)的時(shí)候我們稱做紋理,然后還有一個(gè)很重要的知識點(diǎn),就是所有的紋理圖案都是通過三角形進(jìn)行破解的,然后你就會問了,為什么不是四邊形呢?或者其他的圖形呢?因?yàn)槿切问强梢云唇映蔀楹芏鄨D形,比如四邊形也是兩個(gè)三角形拼接的,五邊形,六邊形也是,然后就是你會發(fā)現(xiàn),在gl上繪制一條直線,其實(shí)他不是很直,他的線條上面會有很多鋸齒,那是因?yàn)槔L制一條直線,需要經(jīng)過很多像素點(diǎn),但是這個(gè)像素點(diǎn)又不在同一條直線上,都是在一條直線的兩側(cè)或者部分在中間,所有你要經(jīng)歷大部分的點(diǎn),因此就有鋸齒。

????然后你要顯示圖像的話,需要在內(nèi)存上開辟一塊區(qū)域用來進(jìn)行計(jì)算,手機(jī)沒有顯存的這個(gè)說法,因?yàn)樗械挠?jì)算都是在內(nèi)存的某個(gè)區(qū)域進(jìn)行計(jì)算的,而且他是最善于計(jì)算的,不會做其他的處理,包括存儲什么的!所有他處理圖像的速度還是很快的,然后他在顯卡中會產(chǎn)生buffer,然后gl就是通過buffer和顯卡進(jìn)行交互來顯示圖像的,這個(gè)buffer你也可以拿來轉(zhuǎn)碼轉(zhuǎn)換為視頻存儲在本地,這個(gè)我們后面再說

? ? 上面的流程還是蠻基礎(chǔ)的,希望大家看完可以收獲一點(diǎn)東西!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容