由于本人現(xiàn)在在公司做Android上的OpenGL圖像處理相關(guān)功能累奈,以前沒有搞過這方面的知識,所以一切只能從頭開始搞起丐膝,接下來將會慢慢分享其他方面的內(nèi)容绍赛,先用這篇比較基礎(chǔ)的文章來開頭。
一鸣个、OpenGL的作用
剛才我們談到圖像處理羞反,在做圖像處理我們不是可以用Canvas來繪制嗎,怎么還要用OpenGL那么陌生的東西來搞囤萤?為什么要用OpenGL昼窗,肯定有它的好處。
- OpenGL的好處:手機(jī)上做圖像處理有很多方式涛舍,但是目前為止最高效的方法是有效地使用圖形處理單元澄惊,或者叫 GPU;GPU 可以集中來處理好一件事情富雅,就是并行地做浮點(diǎn)運(yùn)算掸驱。事實(shí)上,圖像處理和渲染就是在將要渲染到窗口上的像素上做許許多多的浮點(diǎn)運(yùn)算没佑。也就是說用GPU來分擔(dān)CPU的工作毕贼,提高工作效率。
二蛤奢、初始化OpenGL項(xiàng)目
接下來我們會來講解如何在Android項(xiàng)目開發(fā)過程中加入OpenGL鬼癣,在開始前我們先了解同OpenGL ES密切相關(guān)的載體:GLSurfaceView:
- GLSurfaceView會處理OpenGL初始化過程中比較基礎(chǔ)的操作,可以配置顯示設(shè)備以及在后臺線程中渲染啤贩。渲染是在surface的特定區(qū)域中完成的扣溺,也稱為視口。
GLSurfaceView實(shí)際上為它自己創(chuàng)建一個(gè)Window瓜晤,可以當(dāng)做是在視圖層里打穿一個(gè)洞锥余,底層的OpenGL surface顯示出來,但是痢掠,它沒有動(dòng)畫或者變形特效驱犹。
1.創(chuàng)建GLSurfaceView實(shí)例
要用OpenGL繪制嘲恍,首先要有GLSurfaceVie的實(shí)例
private GLSurfaceView glSurfaceView;
private boolean rendererSet = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new GLSurfaceView(this);
setContentView(glSurfaceView);
}
2.檢查系統(tǒng)是否支持OpenGL ES 2.0
現(xiàn)在OpenGL ES版本已經(jīng)到3.0了,Android平臺上目前有1.0和2.0雄驹,我們使用的是2.0佃牛,在使用前在onCreate()方法中檢查是否支持2.0的版本并且確定使用2.0
ActivityManager activityManager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo = activityManager
.getDeviceConfigurationInfo();
final boolean supportsEs2 =
configurationInfo.reqGlEsVersion >= 0x20000
|| (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
&& (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")));
if (supportsEs2) {
glSurfaceView.setEGLContextClientVersion(2);
glSurfaceView.setRenderer(new AirHockeyRenderer(this));
rendererSet = true;
} else {
Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
Toast.LENGTH_LONG).show();
return;
}
一般我們只需要使用“configurationInfo.reqGlEsVersion >= 0x20000”,至于加后面主要是用于模擬器檢查医舆,假定模擬器支持2.0俘侠。
3.為OpenGL ES 2.0配置渲染表面
前面說到GLSurfaceView挖了一個(gè)洞,就是為了看見下面的渲染表面蔬将,同樣實(shí)在onCreate()方法中
if (supportsEs2) {
// Request an OpenGL ES 2.0 compatible context.
glSurfaceView.setEGLContextClientVersion(2);
// Assign our renderer.
glSurfaceView.setRenderer(new FirstOpenGLProjectRenderer());
rendererSet = true;
} else {
Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
Toast.LENGTH_LONG).show();
return;
}
通過setEGLContextClientVersion()方法配置surface視圖爷速,設(shè)定好使用的OpenGL版本,然后調(diào)用setRenderer()傳進(jìn)有自定義Renderer類的新實(shí)例霞怀。當(dāng)Surface創(chuàng)建或者發(fā)生變化的時(shí)候惫东,以及繪制一幅新幀時(shí),渲染器都會被GLSurfaceView調(diào)用毙石。
4.處理Android Activity生命周期的事件
GLSurfaceView的生命周期要協(xié)同好Activity的生命周期廉沮,避免造成內(nèi)存泄漏。
@Override
protected void onPause() {
super.onPause();
if (rendererSet) {
glSurfaceView.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (rendererSet) {
glSurfaceView.onResume();
}
}
4.創(chuàng)建Renderer類
Renderer類也就是我們的渲染類了徐矩,它是通過實(shí)現(xiàn)Renderer接口來實(shí)現(xiàn)功能的滞时。
渲染器接口定義的方法:
- onSurfaceCreated(GL10 glUnused, EGLConfig config):當(dāng)Surface被創(chuàng)建的時(shí)候,GLSurfaceView會調(diào)用這個(gè)方法滤灯,這發(fā)生在應(yīng)用程序創(chuàng)建的第一次漂洋,并且當(dāng)設(shè)備被喚醒或者用戶從其他activity切換回去時(shí),也會被調(diào)用力喷。
- onSurfaceChanged(GL10 glUnused, int width, int height):在Surface創(chuàng)建以后刽漂,每次Surface尺寸變化后,這個(gè)方法都會調(diào)用
- onDrawFrame(GL10 glUnused):當(dāng)繪制每一幀的時(shí)候會被調(diào)用弟孟。
GLSurfaceView會在單獨(dú)一條線程中調(diào)用渲染器的方法贝咙。默認(rèn)情況下,GLSurfaceView會顯示設(shè)備的刷新頻率不斷地渲染拂募,也可以配置按請求渲染庭猩,只需要設(shè)置GLSurfaceVIew.RENDERMODE_WHEN_DIRTY作為參數(shù)調(diào)用GLSurfaceView.setRenderMode()就可以。
GLSurfaceView在后臺線程進(jìn)行渲染陈症,而UI線程是在主線程中調(diào)用的蔼水,所以兩個(gè)線程間的通信可以使用如下方式,在主線程中的GLSurfaceView實(shí)例可以調(diào)用queueEvent()傳遞一個(gè)Runnable給后臺渲染線程录肯,渲染線程可以調(diào)用Activity的runOnUITHread()來傳遞事件給主線程
實(shí)現(xiàn)Renderer的接口方法
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
// Set the background clear color to red. The first component is
// red, the second is green, the third is blue, and the last
// component is alpha, which we don't use in this lesson.
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
}
首選在onSurfaceCreated()中調(diào)用glClearColor設(shè)置清空屏幕用的顏色趴腋,這里使用紅色。
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
// Set the OpenGL viewport to fill the entire surface.
glViewport(0, 0, width, height);
}
設(shè)置視口的大小
@Override
public void onDrawFrame(GL10 glUnused) {
// Clear the rendering surface.
glClear(GL_COLOR_BUFFER_BIT);
}
在onDrawFrame()中調(diào)用glClear(GL_COLOR_BUFFER_BIT)清空屏幕,會調(diào)用glClearColor中定義的顏色來填充整個(gè)屏幕优炬。通過這幾個(gè)步驟颁井,基本上就可以在GLSurfaceView繪制出東西了,在這里我只是簡單的用紅色繪制整個(gè)屏幕蠢护。
OpenGL在Android上的使用基本上是這樣雅宾,但是,當(dāng)然沒那么簡單葵硕,在使用OpenGL進(jìn)行繪制算是比較繁瑣的過程眉抬,后面也會慢慢去揭曉其他使用方法,來構(gòu)造一幅一幅精美的特效靜/動(dòng)圖懈凹。