Android OpenGL ES開發(fā)(三)繪制一個三角形

1、前言

選擇繪制三角形作為OpenGL ES的第一個實例,是因為點、線、三角形是OpenGL ES世界的圖形基礎(chǔ),無論多么復(fù)雜的幾何物體,在OpenGL ES的世界里都可以用三角形拼成

2、步驟

依照官方文檔中的說明,Android中利用OpenGL ES 2.0繪制三角形的步驟為:

2.1在AndroidManifest.xml文件中設(shè)置使用的OpenGL ES的版本:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />
GLSurfaceView glv = findViewById(R.id.glv);
//必須代碼設(shè)置版本
 glv.setEGLContextClientVersion(2);

2.2毫無疑問的,顯示三角形,需要一個載體。創(chuàng)建顯示三角形的Activity,利用GLSurfaceView作為顯示三角形的View,圖形的具體渲染工作都是在Render中完成的。

3. 實現(xiàn)GLSurfaceView的Render,在Render中完成三角形的繪制,具體行為有:

1、加載頂點和片元著色器
2、確定需要繪制圖形的坐標(biāo)和顏色數(shù)據(jù)
3、創(chuàng)建program對象,連接頂點和片元著色器,鏈接program對象。
4、設(shè)置視圖窗口(viewport)。
5、將坐標(biāo)數(shù)據(jù)顏色數(shù)據(jù)傳入OpenGL ES程序中
6、使顏色緩沖區(qū)的內(nèi)容顯示到屏幕上。

3、具體實現(xiàn)

我們設(shè)置好OpenGL ES版本、創(chuàng)建入口Activity并設(shè)置好GLSurfaceView做為顯示載體后,就進入了我們最主要的工作了。

3.1 第一步

首先,我們需要編寫一個簡單的頂點著色器和一個簡單的片元著色器:
頂點著色器:

    private final String vertextShaderCode =
            "attribute vec4 vPosition;"+
            "void main() {"+
            "   gl_Position = vPosition;"+
            "}";

片元著色器:

    private final String fragmentShaderCode =
            "precision mediump float;"+
            "uniform vec4 vColor;"+
            "void main() {"+
            "   gl_FragColor = vColor;"+
            "}";

gl_Position和gl_FragColor都是Shader的內(nèi)置變量,分別為定點位置和片元顏色。

3.2 第二步

然后,我們確定要繪制的圖形的頂點坐標(biāo)和顏色:
我們現(xiàn)在需要繪制的是在一個三維空間中繪制一個三角形,三角形當(dāng)然是三個頂點了。因為我們?nèi)切沃皇且粋€平面圖形。為了方便,我們現(xiàn)在在不設(shè)置相機(相機在后面講)的情況下,三角形正對我們來呈現(xiàn)。所以我們打三個頂點的Z坐標(biāo)都設(shè)置為0。OpenGL ES坐標(biāo)映射到屏幕上,從屏幕中心垂直到上下左右邊緣距離都是1.0,所以(-1.0,0,0)和(0,1.0,0)到原點的距離在屏幕上呈現(xiàn)出來的結(jié)果是不一樣的,圖解如下(左邊是理想狀態(tài),右邊是實際狀態(tài)):


1.png

所以,為了不超出屏幕,我們的坐標(biāo)數(shù)據(jù)設(shè)置為:

    private float triangleCoors[] = {
            0.5f , 0.5f , 0.0f,
            -0.5f , -0.5f , 0.0f,
            0.5f , -0.5f , 0.0f
    };

顏色數(shù)據(jù),我們設(shè)置為單一顏色:

    private float color[] = {
            1.0f , 1.0f , 1.0f , 1.0f
    };

3.3 第三步

接著我們開始在Render中實現(xiàn)我們的三角形繪制了。Render接口有三個方法,分別為

onSurfaceCreated
onSurfaceChanged
onDrawFrame

在onSurfaceCreated方法中,我們來創(chuàng)建program對象,連接頂點和片元著色器,鏈接program對象。

        //設(shè)置背景顏色
        GLES20.glClearColor(0.5f,0.5f,0.5f,0.5f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //申請底層空間
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(triangleCoors.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        //將坐標(biāo)數(shù)據(jù)轉(zhuǎn)換為FloatBuffer,用以傳入給OpenGL ES程序
        vertexBuffer = byteBuffer.asFloatBuffer();
        //將三角形坐標(biāo)傳入FloatBuffer
        vertexBuffer.put(triangleCoors);
        vertexBuffer.position(0);
        //創(chuàng)建頂點著色器程序
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertextShaderCode);
        //創(chuàng)建片元著色器程序
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        if (vertexShader == 0 || fragmentShader == 0)
        {
            return;
        }
        //創(chuàng)建一個空的OpenGL ES程序
        program = GLES20.glCreateProgram();
        //將頂點著色器加入程序
        GLES20.glAttachShader(program, vertexShader);
        //將片元著色器加入程序
        GLES20.glAttachShader(program, fragmentShader);
        //連接到著色器程序中
        GLES20.glLinkProgram(program);
        //將程序加入到OpenGLES2.0環(huán)境
        GLES20.glUseProgram(program);
    public int loadShader(int type , String shaderCode)
    {
        //創(chuàng)建空的著色器
        int shader = GLES20.glCreateShader(type);
        //將著色器程序加到著色器中
        GLES20.glShaderSource(shader,shaderCode);
        //編譯色器程序
        GLES20.glCompileShader(shader);

        return shader;

    }

3.4 第四步

在onSurfaceChanged中設(shè)置視圖窗口:

GLES20.glViewport(0,0,width,height);

3.5 第五步

最后在onDrawFrame中繪制

        if(program == 0)
            return;

        //獲取頂點著色器的vPosition成員句柄
        int vPosition = GLES20.glGetAttribLocation(program, "vPosition");
        //啟用vPosition句柄
        GLES20.glEnableVertexAttribArray(vPosition);
        //傳入但僥幸的坐標(biāo)數(shù)據(jù)
        GLES20.glVertexAttribPointer(vPosition,3,GLES20.GL_FLOAT,false,3*4, vertexBuffer);
        //獲取片元著色器的vColor成員句柄
        int vColor = GLES20.glGetUniformLocation(program, "vColor");
        //設(shè)置繪制三角形的顏色
        GLES20.glUniform4fv(vColor,1,color,0);
        //繪制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3);
        //禁止頂點數(shù)組的句柄
        GLES20.glDisableVertexAttribArray(vPosition);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容