Android建立OpenGL ES的環(huán)境

2018-08-02 17:36 更新

編寫(xiě):jdneo - 原文:http://developer.android.com/training/graphics/opengl/environment.html

要在應(yīng)用中使用OpenGL ES繪制圖像,我們必須為它們創(chuàng)建一個(gè)View容器。一種比較直接的方法是實(shí)現(xiàn)GLSurfaceView類(lèi)和GLSurfaceView.Renderer類(lèi)。其中,GLSurfaceView是一個(gè)View容器,它用來(lái)存放使用OpenGL繪制的圖形,而GLSurfaceView.Renderer則用來(lái)控制在該View中繪制的內(nèi)容。關(guān)于這兩個(gè)類(lèi)的更多信息,你可以閱讀:OpenGL ES開(kāi)發(fā)手冊(cè)。

使用GLSurfaceView是一種將OpenGL ES集成到應(yīng)用中的方法之一。對(duì)于一個(gè)全屏的或者接近全屏的圖形View,使用它是一個(gè)理想的選擇。開(kāi)發(fā)者如果希望把OpenGL ES的圖形集成在布局的一小部分里面,那么可以考慮使用TextureView。對(duì)于喜歡自己動(dòng)手實(shí)現(xiàn)的開(kāi)發(fā)者來(lái)說(shuō),還可以通過(guò)使用SurfaceView搭建一個(gè)OpenGL ES View,但這將需要編寫(xiě)更多的代碼。

在這節(jié)課中,我們將展示如何在一個(gè)的Activity中完成GLSurfaceViewGLSurfaceView.Renderer的最簡(jiǎn)單的實(shí)現(xiàn)。

在Manifest配置文件中聲明使用OpenGL ES

為了讓?xiě)?yīng)用能夠使用OpenGL ES 2.0接口,我們必須將下列聲明添加到Manifest配置文件當(dāng)中:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

如果我們的應(yīng)用使用紋理壓縮(Texture Compression),那么我們必須對(duì)支持的壓縮格式也進(jìn)行聲明,確保應(yīng)用僅安裝在可以兼容的設(shè)備上:

<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />

更多關(guān)于紋理壓縮的內(nèi)容,可以閱讀:OpenGL開(kāi)發(fā)手冊(cè)。

為OpenGL ES圖形創(chuàng)建一個(gè)activity

使用OpenGL ES的安卓應(yīng)用就像其它類(lèi)型的應(yīng)用一樣有自己的用戶接口,即也擁有多個(gè)Activity。主要的區(qū)別體現(xiàn)在Acitivity布局內(nèi)容上的差異。在許多應(yīng)用中你可能會(huì)使用TextView,ButtonListView等,而在使用OpenGL ES的應(yīng)用中,我們還可以添加一個(gè)GLSurfaceView。

下面的代碼展示了一個(gè)使用GLSurfaceView作為其主View的Activity:

public class OpenGLES20Activity extends Activity {

    private GLSurfaceView mGLView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a GLSurfaceView instance and set it
        // as the ContentView for this Activity.
        mGLView = new MyGLSurfaceView(this);
        setContentView(mGLView);
    }
}

Note:OpenGL ES 2.0需要Android 2.2(API Level 8)或更高版本的系統(tǒng),所以確保你的Android項(xiàng)目的API版本滿足該要求。

構(gòu)建一個(gè)GLSurfaceView對(duì)象

GLSurfaceView是一種比較特殊的View,我們可以在該View中繪制OpenGL ES圖形,不過(guò)它自己并不做太多和繪制圖形相關(guān)的任務(wù)。繪制對(duì)象的任務(wù)是由你在該View中配置的GLSurfaceView.Renderer所控制的。事實(shí)上,這個(gè)對(duì)象的代碼非常簡(jiǎn)短,你可能會(huì)希望不要繼承它,直接創(chuàng)建一個(gè)未經(jīng)修改的GLSurfaceView實(shí)例,不過(guò)請(qǐng)不要這么做,因?yàn)槲覀冃枰^承該類(lèi)來(lái)捕捉觸控事件,這方面知識(shí)會(huì)在響應(yīng)觸摸事件(該系列課程的最后一節(jié)課)中做進(jìn)一步的介紹。

GLSurfaceView的核心代碼非常簡(jiǎn)短,所以對(duì)于一個(gè)快速的實(shí)現(xiàn)而言,我們通??梢栽贏citvity中創(chuàng)建一個(gè)內(nèi)部類(lèi)并使用它:

class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;

    public MyGLSurfaceView(Context context){
        super(context);

        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2);

        mRenderer = new MyGLRenderer();

        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(mRenderer);
    }
}

另一個(gè)對(duì)于GLSurfaceView實(shí)現(xiàn)的可選選項(xiàng),是將渲染模式設(shè)置為:GLSurfaceView.RENDERMODE_WHEN_DIRTY,其含義是:僅在你的繪制數(shù)據(jù)發(fā)生變化時(shí)才在視圖中進(jìn)行繪制操作:

// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

如果選用這一配置選項(xiàng),那么除非調(diào)用了requestRender(),否則GLSurfaceView不會(huì)被重新繪制,這樣做可以讓?xiě)?yīng)用的性能及效率得到提高。

構(gòu)建一個(gè)渲染類(lèi)

在一個(gè)使用OpenGL ES的應(yīng)用中,一個(gè)GLSurfaceView.Renderer類(lèi)的實(shí)現(xiàn)(或者我們將其稱(chēng)之為渲染器),正是事情變得有趣的地方。該類(lèi)會(huì)控制和其相關(guān)聯(lián)的GLSurfaceView,具體而言,它會(huì)控制在GLSurfaceView上繪制的內(nèi)容。在渲染器中,一共有三個(gè)方法會(huì)被Android系統(tǒng)調(diào)用,以此來(lái)明確要在GLSurfaceView上繪制的內(nèi)容以及如何繪制:

  • onSurfaceCreated():調(diào)用一次,用來(lái)配置View的OpenGL ES環(huán)境。
  • onDrawFrame():每次重新繪制View時(shí)被調(diào)用。
  • onSurfaceChanged():如果View的幾何形態(tài)發(fā)生變化時(shí)會(huì)被調(diào)用,例如當(dāng)設(shè)備的屏幕方向發(fā)生改變時(shí)。

下面是一個(gè)非常基本的OpenGL ES渲染器的實(shí)現(xiàn),它僅僅在GLSurfaceView中畫(huà)一個(gè)黑色的背景:

public class MyGLRenderer implements GLSurfaceView.Renderer {

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }

    public void onDrawFrame(GL10 unused) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
}

就是這樣!上面的代碼創(chuàng)建了一個(gè)簡(jiǎn)單地應(yīng)用程序,它使用OpenGL讓屏幕呈現(xiàn)為黑色。雖然它的代碼看上去并沒(méi)有做什么非常有意思的事情,但是通過(guò)創(chuàng)建這些類(lèi),我們已經(jīng)對(duì)使用OpenGL繪制圖形有了基本的認(rèn)識(shí)和鋪墊。

Note:你可能想知道,自己明明使用的是OpenGL ES 2.0接口,為什么這些方法會(huì)有一個(gè)GL10的參數(shù)。這是因?yàn)檫@些方法的簽名(Method Signature)在2.0接口中被簡(jiǎn)單地重用了,以此來(lái)保持Android框架的代碼盡量簡(jiǎn)單。

如果你對(duì)OpenGL ES接口很熟悉,那么你現(xiàn)在就可以在你的應(yīng)用中構(gòu)建一個(gè)OpenGL ES的環(huán)境并繪制圖形了。當(dāng)然, 如果你希望獲取更多的幫助來(lái)學(xué)會(huì)使用OpenGL,那么請(qǐng)繼續(xù)學(xué)習(xí)下一節(jié)課程獲取更多的知識(shí)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)