OpenGL ES系列五--圖元形式及繪製方式

OpenGL ES圖元形式及繪製方式

OpenGL ES的繪製主要涉及到兩個方面,一個是圖元繪製,還有一個是繪製方式。下面我們先以圖元繪製開始,下面再講解繪製順序。

圖元繪製(此處默認使用GLES30.glDrawArrays()函數繪製)

在OpenGL ES中支持的繪製圖元有以下三種:點、線、三角形,每一種圖元都有多種繪製方式,我們都會講解說明。以下是示例代碼,感興趣的可以下載下來看一下。

OpenGL ES示例代碼

先上一下我們實例代碼中四個點的座標位置:

//頂點座標數組(每三個一組,共四組,對應四個頂點座標)
val vertexIndexArray = floatArrayOf(
         //x,y,z
         //左上
         -1.0f, 1.0f, 1f,
         //右上
         1.0f, 1.0f, 1f,
         //右下
         1.0f, -1.0f, 1f,
         //左下
         -1.0f, -1.0f, 1f
)

對應的空間座標圖如下:

這裏寫圖片描述

可能畫的不是很好,見諒啊。

點的繪製只有一種即GLES30.GL_POINTS,它會按我們上面定義的順序依次繪製,效果圖如下:

這裏寫圖片描述

在繪製點的時候有一點需要注意:

在OpenGL ES1.0裏面,在java層是有API可以直接設置點大小的:gl.glPointSize(),這裏的gl爲實現GLSurfaceView.Renderer重寫方法中的GL10,但是從OpenGL ES2.0/3.0開始是沒有這個API的,如果要設置點大小,只能在頂點着色器裏面設置,它提供了內置變量gl_PointSize。具體可以下載上面的Demo,裏面都有詳細的註釋。

線的繪製形式有三種:

  • GLES30.GL_LINES。以給定的頂點爲依據,每兩個繪製一條直線,頂點數超過會被丟棄,比如五個頂點,那麼第五個不會繪製出來
  • GLES30.GL_LINE_STRIP。以給定的頂點爲依據,按照頂點順序連接頂點
  • GLES30.GL_LINE_LOOP。以給定的頂點爲依據,按照頂點順序連接頂點,最後會將首尾兩點連接

還是以上面四個點爲例,效果分別如下:

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

三角形

三角形的繪製形式同樣有三種:

  • GL_TRIANGLES。三個點一組,如果不夠三個點就會被丟棄
  • GL_TRIANGLE_STRIP。頂點按照順序依次組成三角形繪製,最後實際形成的是一個三角型帶。
  • GL_TRIANGLE_FAN。將第一個點作爲中心點,其他點作爲邊緣點,繪製一系列的組成扇形的三角形

以上面的4個頂點爲例,效果如下:

這裏寫圖片描述

第四個點由於沒有可以拼成的三角形,被丟棄。

這裏寫圖片描述

這裏寫圖片描述

繪製方式

繪製同樣的圖元,在OpenGL ES中其實是有多種方式的,下面我們就介紹一下常用的,一些不常用的也會列出,可以自己去查詢:

  1. glDrawArrays
  2. glDrawElements
  3. glDrawRangeElements
  4. glDrawArraysInstanced(渲染大量類似對象時使用)
  5. glDrawElementsInstanced(渲染大量類似對象時使用)

我們以1、2爲例,我們上面的效果圖用的都是glDrawArrays,現在我們詳細說明每一個參數的含義:

public static native void glDrawArrays(
    //繪製圖元的形式,就是我們上面一節講的GLES30.GL_GL_TRIANGLES、GLES30.GL_POINTS等
    int mode,
    //第一個頂點索引從多少開始,一般都是從0開始
    int first,
    //要繪製的頂點個數
    int count
)

我們以繪製GL_TRIANGLE_FAN爲例,first設置1,看看效果圖:

這裏寫圖片描述

我們發現當我們索引從1開始時,三角形少了一個,因爲雖然我們繪製的是四個頂點,可是第一個點並沒有繪製,而是從第二個點開始。

現在說明glDrawElements的參數含義:

public static native void glDrawElements(
        //繪製圖元的形式
        int mode,
        //繪製的頂點個數
        int count,
        //頂點參數類型,GL_FLOAT、GL_INT、GL_UNSIGNED_SHORT等
        int type,
        //保存頂點索引數組的緩存數據
        java.nio.Buffer indices
    )

我們以如下順序作爲索引數組

//頂點繪製索引數組
val vertexIndexArray = shortArrayOf(
        //x,y,z
        //右上
        1,
        //右下
        2,
        //左下
        3,
        //左上
        0
)

此時的效果是:

這裏寫圖片描述

補充知識點(爲了看代碼不會懵逼)

編寫OpenGL ES程序的大致流程,這個是在所有OpenGL ES項目中都有涉及到的,基本上都是相同的。

  1. 創建GLSurface子類

    這裏主要是做一些初始化操作,比如初始化版本、初始化渲染器、設置渲染器、設置渲染模式

  2. 渲染器的初始化

    渲染器爲GLSurfaceView.Renderer的子實現類,主要是重寫三個方法:onSurfaceCreated、onSurfaceChanged、onDrawFrame,在這三個函數中做一些不同的邏輯處理。onSurfaceCreated主要是做一些初始化配置,比如初始化算法實例(算法類裏面會定義頂點相關數據,繪製操作等,相當於把所有的邏輯都放在這裏,當然你也可以不這麼做,按自己的想法來搞)、初始化着色器程序、初始化着色器變量句柄(可以理解爲着色器變量的唯一標識);onSurfaceChanged主要是做視口設置、相機位置設置、投影矩陣設置等;onDrawFrame則是爲着色器傳遞數據,並繪製

  3. 算法類實例化時做一些初始化操作–初始化頂點數據、初始化着色器和句柄

    初始化頂點數據:這一步其實就是第二步中onSurfaceCreated執行的邏輯,我們在這裏會初始化頂點座標、頂點顏色、頂點紋理、頂點索引、頂點法向量等等

    初始化着色器和句柄:這一步也是在第二步中onSurfaceCreated執行的邏輯,我們需要讀取着色器源碼,然後傳遞給相應的API來創建着色器程序,一旦創建成功,我們需要從着色器程序中獲取着色器變量的句柄(可以理解爲着色器變量的唯一標識),後面繪製時我們可以根據這個句柄爲着色器變量傳值

  4. 算法類的onCreate方法,對應onSurfaceCreated

    這裏我們主要是做設置背景、根據需要開啓一些被禁用的功能(比如深度測試、混合等等)、初始化線程等

  5. 算法類的onChange方法,對應onSurfaceChanged

    主要是設置視口、設置相機、設置投影等

  6. 算法類的onDraw方法,對應onDrawFrame

    主要是配置着色器程序、爲着色器變量(句柄)賦值、矩陣變換(平移、旋轉、縮放…)、繪製相應的圖元等

有了上面一個大致順序的說明,在看demo的時候纔不會暈。到這裏也已經差不多了,如有什麼不足之處還請指出,互相學習。

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