《OpenGL從入門到放棄04》畫一個長方形

之前文章:

《OpenGL從入門到放棄01 》一些基本概念
《OpenGL從入門到放棄02 》GLSurfaceView和Renderer
《OpenGL從入門到放棄03 》相機和視圖

上一篇已經(jīng)介紹了使用相機和視圖,解決三角形位置問題,這一篇我們在三角形的基礎(chǔ)上修改,畫一個長方形。

一、修改頂點

static float triangleCoords[] = {
           -1f, 0.5f, 0.0f, // top left
           -1f, -0.5f, 0.0f, // bottom left
            1f, 0.5f, 0.0f,  // top right
            1f, -0.5f, 0.0f  // bottom right
    };

長方形4個頂點,沒毛病。

二、繪制

方法1,頂點法
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount);

GLES20 .GL_TRIANGLE_STRIP 不清楚?等下會介紹。

方法2,索引法

增加索引代碼,并且要轉(zhuǎn)換成 ShortBuffer

//用索引表示兩個三角形,012和123
    static short index[]={
            0,1,2,1,2,3
    };
//索引數(shù)據(jù)要在OpenGL中使用必須轉(zhuǎn)換
  indexBuffer = GLUtil.shortArray2ShortBuffer(index);

  //索引法繪制,也就是一個正方形
  GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP,index.length, GLES20.GL_UNSIGNED_SHORT,indexBuffer);

兩種方法繪制的結(jié)果是一樣的


說明:

GLES20.glDrawArrays 的第一個參數(shù)表示繪制方式,第二個參數(shù)表示偏移量,第三個參數(shù)表示頂點個數(shù)。
繪制方式有:

int GL_POINTS       //將傳入的頂點坐標作為單獨的點繪制
int GL_LINES        //將傳入的坐標作為單獨線條繪制,ABCDEFG六個頂點,繪制AB、CD、EF三條線
int GL_LINE_STRIP   //將傳入的頂點作為折線繪制,ABCD四個頂點,繪制AB、BC、CD三條線
int GL_LINE_LOOP    //將傳入的頂點作為閉合折線繪制,ABCD四個頂點,繪制AB、BC、CD、DA四條線。
int GL_TRIANGLES    //將傳入的頂點作為單獨的三角形繪制,ABCDEF繪制ABC,DEF兩個三角形
int GL_TRIANGLE_FAN    //將傳入的頂點作為扇面繪制,ABCDEF繪制ABC、ACD、ADE、AEF四個三角形
int GL_TRIANGLE_STRIP   //將傳入的頂點作為三角條帶繪制,ABCDEF繪制ABC,BCD,CDE,DEF四個三角形

GLES20.glDrawElements 稱之為索引法,是根據(jù)索引序列,在頂點序列中找到對應(yīng)的頂點,并根據(jù)繪制的方式,組成相應(yīng)的圖元進行繪制。

頂點法擁有的繪制方式,索引法也都有。相對于頂點法在復(fù)雜圖形的繪制中無法避免大量頂點重復(fù)的情況,索引法可以相對頂點法減少很多重復(fù)頂點占用的空間。


完整代碼如下

/**
 * 正方形
 * 在三角形基礎(chǔ)修改
 */
public class Square {

    // 頂點著色器的腳本
    String vertexShaderCode =
            "uniform mat4 uMVPMatrix;" +         //接收傳入的轉(zhuǎn)換矩陣
                    " attribute vec4 vPosition;" +      //接收傳入的頂點
                    " void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +  //矩陣變換計算之后的位置
                    " }";

    // 片元著色器的腳本
    String fragmentShaderCode =
            " precision mediump float;" +  // 聲明float類型的精度為中等(精度越高越耗資源)
                    " uniform vec4 vColor;" +       // 接收傳入的顏色
                    " void main() {" +
                    "     gl_FragColor = vColor;" +  // 給此片元的填充色
                    " }";

    private FloatBuffer vertexBuffer;  //頂點坐標數(shù)據(jù)要轉(zhuǎn)化成FloatBuffer格式
    private ShortBuffer indexBuffer; //所引法需要


    // 數(shù)組中每3個值作為一個坐標點
    static final int COORDS_PER_VERTEX = 3;
    //正方形坐標數(shù)組
    static float triangleCoords[] = {
           -1f, 0.5f, 0.0f, // top left
           -1f, -0.5f, 0.0f, // bottom left
            1f, 0.5f, 0.0f,  // top right
            1f, -0.5f, 0.0f  // bottom right
    };

    //用索引表示兩個三角形,012和123
    static short index[]={
            0,1,2,1,2,3
    };

    //頂點個數(shù),計算得出
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    //一個頂點有3個float,一個float是4個字節(jié),所以一個頂點要12字節(jié)
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per mVertex

    //三角形的顏色數(shù)組,rgba
    private float[] mColor = {
            0.0f, 1.0f, 0.0f, 1.0f,
    };

    //當前繪制的頂點位置句柄
    private int vPositionHandle;
    //片元著色器顏色句柄
    private int vColorHandle;
    //變換矩陣句柄
    private int mMVPMatrixHandle;
    //這個可以理解為一個OpenGL程序句柄
    private final int mProgram;

    //變換矩陣,提供set方法
    private float[] mvpMatrix = new float[16];
    public void setMvpMatrix(float[] mvpMatrix) {
        this.mvpMatrix = mvpMatrix;
    }


    public Square() {
        /** 1、數(shù)據(jù)轉(zhuǎn)換,頂點坐標數(shù)據(jù)float類型轉(zhuǎn)換成OpenGL格式FloatBuffer,int和short同理*/
        vertexBuffer = GLUtil.floatArray2FloatBuffer(triangleCoords);
        indexBuffer = GLUtil.shortArray2ShortBuffer(index);

        /** 2、加載編譯頂點著色器和片元著色器*/
        int vertexShader = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        /** 3、創(chuàng)建空的OpenGL ES程序,并把著色器添加進去*/
        mProgram = GLES20.glCreateProgram();

        // 添加頂點著色器到程序中
        GLES20.glAttachShader(mProgram, vertexShader);

        // 添加片段著色器到程序中
        GLES20.glAttachShader(mProgram, fragmentShader);

        /** 4、鏈接程序*/
        GLES20.glLinkProgram(mProgram);

    }


    public void draw() {

        // 將程序添加到OpenGL ES環(huán)境
        GLES20.glUseProgram(mProgram);

        /***1.獲取句柄*/
        // 獲取頂點著色器的位置的句柄(這里可以理解為當前繪制的頂點位置)
        vPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        // 獲取片段著色器的vColor句柄
        vColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        // 獲取變換矩陣的句柄
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

        /**2.設(shè)置數(shù)據(jù)*/
        // 啟用頂點屬性,最后對應(yīng)禁用
        GLES20.glEnableVertexAttribArray(vPositionHandle);

        //準備三角形坐標數(shù)據(jù)
        GLES20.glVertexAttribPointer(vPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        // 設(shè)置繪制三角形的顏色,給vColor 這個變量賦值
        GLES20.glUniform4fv(vColorHandle, 1, mColor, 0);
        // 將投影和視圖轉(zhuǎn)換傳遞給著色器,可以理解為給uMVPMatrix這個變量賦值為mvpMatrix
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

        /** 3.繪制正方形,4個頂點, GL_TRIANGLE_STRIP的方式繪制連續(xù)的三角形*/
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount);
//        索引法繪制兩個三角形,也就是一個正方形
//        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP,index.length, GLES20.GL_UNSIGNED_SHORT,indexBuffer);

        // 禁用頂點數(shù)組
        GLES20.glDisableVertexAttribArray(vPositionHandle);
    }
}

好了,長方形的繪制很簡單,本質(zhì)上就是畫兩個三角形,其它復(fù)雜的圖形也是如此,由多個簡單的圖形組成。

下一篇介紹一下著色器語言,然后就開始比較有意思的紋理和圖片處理,敬請期待吧~

最后編輯于
?著作權(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)容