我的CSDN博客同步發(fā)布:Android OpenGL入門
轉(zhuǎn)載請注明出處:【huachao1001的簡書:http://www.reibang.com/users/0a7e42698e4b/latest_articles】
如今VR
這么火觉既,感覺有必要先把OpenGL
學(xué)好,為以后轉(zhuǎn)VR
奠定一些基礎(chǔ)埃唯。一年前纤掸,接觸過Android
的OpenGL
,當(dāng)時(shí)是實(shí)現(xiàn)了在Android
上顯示標(biāo)準(zhǔn)的3D
文件(STL
格式)∶潮希現(xiàn)在打算整理一下OpenGL
相關(guān)知識试躏,后續(xù)會有相關(guān)的系列文章斩披。本文為后面文章鋪墊端姚,讓大家對OpenGL
代碼編寫有個(gè)總體上的認(rèn)識晕粪。
1 檢測設(shè)備是否支持OpenGL
Android
中,有個(gè)專門用于顯示OpenGL
的3D
圖像View
:GLSurfaceView
渐裸。GLSurfaceView
會處理OpenGL
初始化過程中比較基本的操作巫湘,如配置顯示設(shè)備,以及在后臺線程中渲染昏鹃。說的太正式了哈尚氛,其實(shí)不用太在乎它,就把它當(dāng)當(dāng)成是一個(gè)SurfaceView
就好洞渤,因?yàn)槠鋵?shí)它的用法跟SurfaceView
很像(然而阅嘶,它就是繼承自SurfaceView
~)。
接下來開始創(chuàng)建GLSurfaceView
载迄。在使用OpenGL
時(shí)讯柔,我們首先得判斷當(dāng)前設(shè)備是否支持OpenGL
(其實(shí)大部分手機(jī)都是支持的啦~)抡蛙,由于各種設(shè)備都可能支持Android
系統(tǒng),其實(shí)還是有必要判斷一下磷杏。因?yàn)槲覀儸F(xiàn)在基本上用到的是OpenGL ES 2.0
溜畅,我們要驗(yàn)證的是檢查系統(tǒng)是否實(shí)際支持2.0版本捏卓。
final ActivityManager activityManager=(ActivityManager)getSystemService(ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo=activityManager.getDeviceConfigurationInfo();
boolean supportsEs2=configurationInfo.reqGlEsVersion>=0x2000;
由于這段代碼不能很好的在模擬器上工作(GPU
模擬部分有缺陷)极祸,得要稍微修改一下,使之能在模擬器上正常工作
boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;
boolean isEmulator = 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"));
supportsEs2 = supportsEs2 || isEmulator;
我們看看怎么使用GLSurfaceView
吧~
private boolean supportsEs2;
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkSupported();
if (supportsEs2) {
glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setRenderer(new GLRenderer());
setContentView(glSurfaceView);
} else {
setContentView(R.layout.activity_main);
Toast.makeText(this, "當(dāng)前設(shè)備不支持OpenGL ES 2.0!", Toast.LENGTH_SHORT).show();
}
}
private void checkSupported() {
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;
boolean isEmulator = 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"));
supportsEs2 = supportsEs2 || isEmulator;
}
什么怠晴?這么簡單遥金,難道這樣就能顯示3D
模型?可是并沒有看到3D
模型圖形在哪里八馓铩稿械!別著急,看看第9
行代碼冲粤,有個(gè)setRenderer()
函數(shù)美莫,里面需要傳入一個(gè)Renderer
對象,那么什么是Renderer
呢梯捕?前面提到GLSurfaceView
是用于顯示3D模型的視圖厢呵,如果說GLSurfaceView
是畫布,那么傀顾,光有一塊白紙是沒用的襟铭,得要在白紙上畫圖,通過什么畫圖呢短曾?就是接下來要說的Renderer
寒砖。Renderer
是一個(gè)接口,它主要包含3個(gè)抽象函數(shù):onSurfaceCreated
嫉拐、onDrawFrame
哩都、onSurfaceChanged
;從名字就可以看出,分別是在SurfaceView
創(chuàng)建時(shí)調(diào)用婉徘、在繪制圖形時(shí)調(diào)用以及在視圖大小發(fā)生改變時(shí)調(diào)用茅逮。看看我們的GLRenderer
對象是怎么定義的:
/**
* Package com.hc.opengl
* Created by HuaChao on 2016/7/27.
*/
public class GLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
@Override
public void onDrawFrame(GL10 gl) {
}
}
這里啥也沒干判哥,所以你的屏幕上面啥都沒有~但是大致框架已經(jīng)搭建好了献雅。另外,還需要注意一點(diǎn)塌计,就是防止我們在切換程序時(shí)挺身,OpenGL
還在繪制圖形導(dǎo)致程序崩潰,因此我們還需要根據(jù)Activity
的生命周期針對GLSurfaceView
做一些處理:
@Override
protected void onPause() {
super.onPause();
if (glSurfaceView != null) {
glSurfaceView.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (glSurfaceView != null) {
glSurfaceView.onResume();
}
}
ok
锌仅,到目前為止章钾,這個(gè)框架算是搭建好了墙贱,接下來,讓我們把戰(zhàn)場轉(zhuǎn)移到Renderer
對象上去吧贱傀!
2 Renderer顯示背景顏色
在繪制3D
模型時(shí)惨撇,我們首先要對畫板的背景顏色繪制好,顏色可以隨便選府寒。glClearColor
函數(shù)是設(shè)置清屏的顏色魁衙,參數(shù)分別對應(yīng)RGBA
,我們設(shè)置為紅色就是glClearColor(1f, 0f, 0f, 0f);
,為啥紅色是1
呢株搔?而不是我們平時(shí)所熟知的255
剖淀,請注意:在使用OpenGL時(shí),很多地方采用的參數(shù)變化范圍都是從0到1纤房,比如在貼紋理的時(shí)候選擇圖片區(qū)域也是[0,1]纵隔。也就是說,rgba
的取值都是從0~1
炮姨。然后是設(shè)置視角窗口大小glViewport
捌刮,其實(shí)就是決定繪制的矩形區(qū)域的大小,當(dāng)然并不是這么簡單舒岸,后面我會詳細(xì)講绅作,目前就可以把它理解為繪制的區(qū)域,在GLSurfaceView
窗口大小發(fā)生變化時(shí)我們動態(tài)改變視角窗口吁津。最后就是真正的繪制圖形啦棚蓄,我們先啥也不干,就針對畫板“刷一次油漆”碍脏,把畫板背景顏色設(shè)置為紅色梭依,glClear(GL10.GL_COLOR_BUFFER_BIT)
的意思是,使用glClearColor函數(shù)所設(shè)置的顏色進(jìn)行清屏典尾。
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(1f, 0f, 0f, 0f);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
}
運(yùn)行一下吧役拴,是不是看到滿滿的紅色~。如果你的模擬器沒有顯示效果:請檢查“Use Host GPU”選項(xiàng)已經(jīng)勾選钾埂。如果已經(jīng)勾選河闰,那就在 glSurfaceView.setRenderer(new GLRenderer());
代碼之前添加代碼:glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
目前我們把基本框架寫好了,但是還沒有繪制模型圖像褥紫,其實(shí)姜性,我們在顯示模型時(shí),主要的工作就是集中在Renderer髓考,重寫里面的3個(gè)重要函數(shù)部念,基本上就可以把一個(gè)模型顯示出來。下一篇文章中,我們一起學(xué)習(xí)如何顯示簡單的圖形儡炼。