我的簡書同步發佈:Android OpenGL入門
轉載請註明出處:【huachao1001的專欄:http://blog.csdn.net/huachao1001】
如今VR
這麼火,感覺有必要先把OpenGL
學好,爲以後轉VR
奠定一些基礎。一年前,接觸過Android
的OpenGL
,當時是實現了在Android
上顯示標準的3D
文件(STL
格式)。現在打算整理一下OpenGL
相關知識,後續會有相關的系列文章。本文爲後面文章鋪墊,讓大家對OpenGL
代碼編寫有個總體上的認識。
1 檢測設備是否支持OpenGL
Android
中,有個專門用於顯示OpenGL
的3D
圖像View
:GLSurfaceView
。GLSurfaceView
會處理OpenGL
初始化過程中比較基本的操作,如配置顯示設備,以及在後臺線程中渲染。說的太正式了哈,其實不用太在乎它,就把它噹噹成是一個SurfaceView
就好,因爲其實它的用法跟SurfaceView
很像(然而,它就是繼承自SurfaceView
~)。
接下來開始創建GLSurfaceView
。在使用OpenGL
時,我們首先得判斷當前設備是否支持OpenGL
(其實大部分手機都是支持的啦~),由於各種設備都可能支持Android
系統,其實還是有必要判斷一下。因爲我們現在基本上用到的是OpenGL ES 2.0
,我們要驗證的是檢查系統是否實際支持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, "當前設備不支持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
行代碼,有個setRenderer()
函數,裏面需要傳入一個Renderer
對象,那麼什麼是Renderer
呢?前面提到GLSurfaceView
是用於顯示3D模型的視圖,如果說GLSurfaceView
是畫布,那麼,光有一塊白紙是沒用的,得要在白紙上畫圖,通過什麼畫圖呢?就是接下來要說的Renderer
。Renderer
是一個接口,它主要包含3個抽象函數:onSurfaceCreated
、onDrawFrame
、onSurfaceChanged
;從名字就可以看出,分別是在SurfaceView
創建時調用、在繪製圖形時調用以及在視圖大小發生改變時調用。看看我們的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) {
}
}
這裏啥也沒幹,所以你的屏幕上面啥都沒有~但是大致框架已經搭建好了。另外,還需要注意一點,就是防止我們在切換程序時,OpenGL
還在繪製圖形導致程序崩潰,因此我們還需要根據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
,到目前爲止,這個框架算是搭建好了,接下來,讓我們把戰場轉移到Renderer
對象上去吧!
2 Renderer顯示背景顏色
在繪製3D
模型時,我們首先要對畫板的背景顏色繪製好,顏色可以隨便選。glClearColor
函數是設置清屏的顏色,參數分別對應RGBA
,我們設置爲紅色就是glClearColor(1f, 0f, 0f, 0f);
,爲啥紅色是1
呢?而不是我們平時所熟知的255
,請注意:在使用OpenGL時,很多地方採用的參數變化範圍都是從0到1,比如在貼紋理的時候選擇圖片區域也是[0,1]。也就是說,rgba
的取值都是從0~1
。然後是設置視角窗口大小glViewport
,其實就是決定繪製的矩形區域的大小,當然並不是這麼簡單,後面我會詳細講,目前就可以把它理解爲繪製的區域,在GLSurfaceView
窗口大小發生變化時我們動態改變視角窗口。最後就是真正的繪製圖形啦,我們先啥也不幹,就針對畫板“刷一次油漆”,把畫板背景顏色設置爲紅色,glClear(GL10.GL_COLOR_BUFFER_BIT)
的意思是,使用glClearColor函數所設置的顏色進行清屏。
@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);
}
運行一下吧,是不是看到滿滿的紅色~。如果你的模擬器沒有顯示效果:請檢查“Use Host GPU”選項已經勾選。如果已經勾選,那就在 glSurfaceView.setRenderer(new GLRenderer());
代碼之前添加代碼:glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
目前我們把基本框架寫好了,但是還沒有繪製模型圖像,其實,我們在顯示模型時,主要的工作就是集中在Renderer,重寫裏面的3個重要函數,基本上就可以把一個模型顯示出來。下一篇文章中,我們一起學習如何顯示簡單的圖形。