android studio上第一個opengl es程序

閱讀本文前如果是初次接觸opengl可以先閱讀前文:
openGL 3D圖形和openGL簡介:
http://blog.csdn.net/pangrui201/article/details/75091501

android上opengl es基礎知識

           Google在Android2.2 以後支持 opengl es 2.2,在Android 4.3以後引入opengl es 3.0。Android中使用openGL會用到GLSurfaceView控件, GLSurfaceView.Renderer,在Android studio的debug模式下我們可以清楚的看到Renderer的各個回調函數發生在非UI主線程,即渲染線程,具體渲染是在一塊稱爲”surface”(在openGL裏面稱爲ViewPort視口)的地方完成,渲染繪製完成後在將渲染結果直接在主線程顯示,實際上GLSurfaceView在View Hierarchy上”穿洞”,讓底層open gl surface顯示出來。同時,需要考慮GLSurfaceView和Activity的各個生命週期的問題。
另一方面,在Android 4.0以後提供了一個紋理視圖(TextureView)可以也可以渲染opengl,TextureView像普通view一樣不在需要”穿洞”了,但是TextureView沒有內置opengl的初始化操作。

第一個opengl es程序

如下代碼是在Android studio上創建的第一個opengl es項目:

public class MainActivity extends AppCompatActivity {

    private GLSurfaceView glSurfaceView;
    private boolean rendererSet;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        glSurfaceView = new GLSurfaceView(this);

        // Check if the system supports OpenGL ES 2.0.
        final ActivityManager activityManager =
                (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

        final ConfigurationInfo configurationInfo =
                activityManager.getDeviceConfigurationInfo();
        /*

        final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;
         */
        // Even though the latest emulator supports OpenGL ES 2.0,
        // it has a bug where it doesn't set the reqGlEsVersion so
        // the above check doesn't work. The below will detect if the
        // app is running on an emulator, and assume that it supports
        // OpenGL ES 2.0.
        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) {
            // Request an OpenGL ES 2.0 compatible context.
            glSurfaceView.setEGLContextClientVersion(2);

            // Assign our renderer.
            glSurfaceView.setRenderer(new FirstOpenGLProjectRenderer());
            rendererSet = true;
        } else {
            /*
             * This is where you could create an OpenGL ES 1.x compatible
             * renderer if you wanted to support both ES 1 and ES 2. Since we're
             * not doing anything, the app will crash if the device doesn't
             * support OpenGL ES 2.0. If we publish on the market, we should
             * also add the following to AndroidManifest.xml:
             * 
             * <uses-feature android:glEsVersion="0x00020000"
             * android:required="true" />
             * 
             * This hides our app from those devices which don't support OpenGL
             * ES 2.0.
             */
            Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
                    Toast.LENGTH_LONG).show();
            return;
        }

        setContentView(glSurfaceView);
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (rendererSet) {
            glSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (rendererSet) {
            glSurfaceView.onResume();
        }
    }
}

supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;是用來判斷是否支持opengl es2.0,同時在模擬器的話可能支持不是多好,所以代碼進行了判斷。 glSurfaceView.setEGLContextClientVersion(2);是來具體設置opengl版本,配置surface視圖。同時需要注意Activity的生命週期需要回調glSurfaceView對應的生命週期,這樣surface視圖才能正確處理渲染線程暫停和繼續,同時釋放和續用opengl的上下文。

下面是FirstOpenGLProjectRenderer 的代碼:

public class FirstOpenGLProjectRenderer implements Renderer {
    @Override
    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);
    }

    /**
     * onSurfaceChanged is called whenever the surface has changed. This is
     * called at least once when the surface is initialized. Keep in mind that
     * Android normally restarts an Activity on rotation, and in that case, the
     * renderer will be destroyed and a new one created.
     * 
     * @param width
     *            The new width, in pixels.
     * @param height
     *            The new height, in pixels.
     */
    @Override
    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        // Set the OpenGL viewport to fill the entire surface.
        glViewport(0, 0, width, height);
    }

    /**
     * OnDrawFrame is called whenever a new frame needs to be drawn. Normally,
     * this is done at the refresh rate of the screen.
     */
    @Override
    public void onDrawFrame(GL10 glUnused) {
        // Clear the rendering surface.
        glClear(GL_COLOR_BUFFER_BIT);
    }
}

主要有三個回調方法,onSurfaceCreated,onSurfaceChanged,onDrawFrame。之前已經說過了,這些方法回調發生在渲染線程。onSurfaceCreated是在surface被創建時,GLSurfaceView會回調這個方法。onSurfaceChanged是在surface被創建後每次在surface尺寸發生變化的時候GLSurfaceView會回調,比如橫豎屏切換會回調這個方法。onDrawFrame是當每繪製一幀就會被GLSurfaceView回調,通常一定要在這個方法裏做點事情哪怕是設置清屏顏色,因爲這個方法調用之後會把渲染結果surface給屏幕顯示,不能說什麼都沒有,這樣的話可能會顯示花屏。另外,通常GLSurfaceView會以顯示屏的的刷新頻率來回調onDrawFrame進行渲染,當然我們可以設置GLSurfaceView的渲染模式來修改,調用
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
//GLSurfaceView.RENDERMODE_CONTINUOUSLY:持續渲染(默認)
//GLSurfaceView.RENDERMODE_WHEN_DIRTY:髒渲染,命令渲染;即有兩種渲染模式髒渲染和持續渲染(默認)。使用髒渲染需要和glSurfaceView.requestRender配合使用。
           綜上分析,在onSurfaceCreated裏需要設置清屏色,本文爲紅色 glClearColor(1.0f, 0.0f, 0.0f, 0.0f);在onSurfaceChanged裏設置視口viewport大小即通知opengl需要渲染視口大小即surface大小。注意:視口viewport是opengl裏面的概念,surface是GLSurfaceView裏提供給底層渲染顯示的區域,故可以理解爲同一個。在onDrawFrame裏面 glClear(GL_COLOR_BUFFER_BIT);是清楚所有顏色緩衝器,這樣就會顯示清屏色即 glClearColor(1.0f, 0.0f, 0.0f, 0.0f)設置的紅色。
           到此,本文章結束。主要講解基礎概念,基礎原理。本文代碼地址:
https://github.com/pangrui201/OpenGlesProject/tree/master/OpenGlesProject_lesson1

發佈了46 篇原創文章 · 獲贊 22 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章