Android OpenGL入門

我的簡書同步發佈:Android OpenGL入門

轉載請註明出處:【huachao1001的專欄:http://blog.csdn.net/huachao1001】

如今VR這麼火,感覺有必要先把OpenGL學好,爲以後轉VR奠定一些基礎。一年前,接觸過AndroidOpenGL,當時是實現了在Android上顯示標準的3D文件(STL格式)。現在打算整理一下OpenGL相關知識,後續會有相關的系列文章。本文爲後面文章鋪墊,讓大家對OpenGL代碼編寫有個總體上的認識。

1 檢測設備是否支持OpenGL

Android中,有個專門用於顯示OpenGL3D圖像ViewGLSurfaceViewGLSurfaceView會處理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是畫布,那麼,光有一塊白紙是沒用的,得要在白紙上畫圖,通過什麼畫圖呢?就是接下來要說的RendererRenderer是一個接口,它主要包含3個抽象函數:onSurfaceCreatedonDrawFrameonSurfaceChanged;從名字就可以看出,分別是在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個重要函數,基本上就可以把一個模型顯示出來。下一篇文章中,我們一起學習如何顯示簡單的圖形。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章