附錄(6)使用頂點(diǎn)緩存區(qū)繪制

頂點(diǎn)緩存區(qū)在第六章已經(jīng)說過,這里整理一個(gè)案例体谒。還是最簡(jiǎn)單的代碼杯聚,繪制一個(gè)三角形。這案例繼承附錄5中的基類抒痒。

不使用頂點(diǎn)緩存區(qū)

/**
 * 三角形
 */
public class Triangle extends BaseGameScreen {
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

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

    static final int COORDS_PER_VERTEX = 3;
    private FloatBuffer vertexBuffer;
    static float triangleCoords[] = {
            0.5f,  0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f  // bottom right
    };

    //頂點(diǎn)個(gè)數(shù)
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    //頂點(diǎn)之間的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)
    //設(shè)置顏色械媒,依次為紅綠藍(lán)和透明通道
    float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    private int mPositionHandle;
    private int mColorHandle;
    float d = 0.01F;
    public Triangle(){

    }

    public void create(){
        ByteBuffer bb = ByteBuffer.allocateDirect(
                triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
        mProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgram,vertexShader);
        GLES20.glAttachShader(mProgram,fragmentShader);
        GLES20.glLinkProgram(mProgram);
        //程序加入到環(huán)境里面
        GLES20.glUseProgram(mProgram);
//        檢查是否有效
        GLES20.glValidateProgram(mProgram);
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    }


    @Override
    public void surfaceChange(int width, int height) {
        GLES20.glViewport(0,0,width,height);
    }

    @Override
    public void dispose() {

    }


    @Override
    public void render() {
        //獲取位置句柄   屬性句柄

        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //準(zhǔn)備三角形的坐標(biāo)數(shù)據(jù)
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                vertexBuffer);
        //獲取片元著色器的vColor成員的句柄

        color[1] = color[1]-d;
        if (color[1]<=0||color[1]>=1){
            d=-d;
        }
        //設(shè)置繪制三角形的顏色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        //繪制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        //禁止頂點(diǎn)數(shù)組的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

}

使用頂點(diǎn)緩存區(qū)

package com.example.myapplication.learn.shape;

import android.opengl.GLES20;

import com.example.myapplication.MainActivity;
import com.example.myapplication.learn.shape.base.BaseGameScreen;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

/**
 * 三角形
 */
public class TriangleBuffer extends BaseGameScreen {
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

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

    static final int COORDS_PER_VERTEX = 3;
    private FloatBuffer vertexBuffer;
    static float triangleCoords[] = {
            0.5f,  0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f  // bottom right
    };

    //頂點(diǎn)個(gè)數(shù)
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    //頂點(diǎn)之間的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)
    //設(shè)置顏色,依次為紅綠藍(lán)和透明通道
    float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    private int mPositionHandle;
    private int mColorHandle;
    float d = 0.01F;
    public TriangleBuffer(MainActivity activity){

    }

    public void create(){
        ByteBuffer bb = ByteBuffer.allocateDirect(
                triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        createVBO();

        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
        mProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgram,vertexShader);
        GLES20.glAttachShader(mProgram,fragmentShader);
        GLES20.glLinkProgram(mProgram);
        //程序加入到環(huán)境里面
        GLES20.glUseProgram(mProgram);
//        檢查是否有效
        GLES20.glValidateProgram(mProgram);
        //得到活躍的unifor
        int arr[] = new int[1];
        int arr1[] = new int[1];
        int arr2[] = new int[1];
        int arr3[] = new int[1];
        byte arr4[] = new byte[10];
        GLES20.glGetProgramiv(mProgram,GLES20.GL_ACTIVE_UNIFORMS,arr,0);
        GLES20.glGetActiveUniform(
                mProgram,
                1,
                1,
                arr1,
                1,
                arr2,
                1,
                arr3,
                1,
                arr4,
                0
                );
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    }


    @Override
    public void surfaceChange(int width, int height) {
        GLES20.glViewport(0,0,width,height);
    }

    @Override
    public void dispose() {

    }


    @Override
    public void render() {
        //獲取位置句柄   屬性句柄

        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //準(zhǔn)備三角形的坐標(biāo)數(shù)據(jù)
        useVboDraw();
//        GLES20.glVertexAttribPointer(
//                mPositionHandle,
//                COORDS_PER_VERTEX,
//                GLES20.GL_FLOAT,
//                false,
//                vertexStride,
//                vertexBuffer);
        //獲取片元著色器的vColor成員的句柄

        color[1] = color[1]-d;
        if (color[1]<=0||color[1]>=1){
            d=-d;
        }
        //設(shè)置繪制三角形的顏色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        //繪制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        //禁止頂點(diǎn)數(shù)組的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

    int vboId = 0;
    private void createVBO() {
        //1. 創(chuàng)建VBO
        int[] vbos = new int[1];
        GLES20.glGenBuffers(vbos.length, vbos, 0);
        vboId = vbos[0];
        //2. 綁定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //3. 分配VBO需要的緩存大小
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
                triangleCoords.length * 4 +
                        triangleCoords.length * 4,
                null, GLES20.GL_STATIC_DRAW);
        //4. 為VBO設(shè)置頂點(diǎn)數(shù)據(jù)的值
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER,
                0,
                triangleCoords.length * 4,
                vertexBuffer);
//        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, textureData.length * 4, textureBuffer);
        //5. 解綁VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

    private void useVboDraw() {
        //1. 綁定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //2. 設(shè)置頂點(diǎn)數(shù)據(jù)
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                0);

        //3. 解綁VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }
}

區(qū)別在哪里评汰,只有兩個(gè)地方,第一個(gè)創(chuàng)建緩存區(qū)放入數(shù)據(jù)痢虹,第二個(gè)是使用緩存區(qū)被去。

   private void createVBO() {
        //1. 創(chuàng)建VBO
        int[] vbos = new int[1];
        GLES20.glGenBuffers(vbos.length, vbos, 0);
        vboId = vbos[0];
        //2. 綁定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //3. 分配VBO需要的緩存大小
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
                triangleCoords.length * 4 +
                        triangleCoords.length * 4,
                null, GLES20.GL_STATIC_DRAW);
        //4. 為VBO設(shè)置頂點(diǎn)數(shù)據(jù)的值
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER,
                0,
                triangleCoords.length * 4,
                vertexBuffer);
//        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, textureData.length * 4, textureBuffer);
        //5. 解綁VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

第二個(gè)是使用

   private void useVboDraw() {
        //1. 綁定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //2. 設(shè)置頂點(diǎn)數(shù)據(jù)
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                0);

        //3. 解綁VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

創(chuàng)建部分,不需要做任何修改脆丁, 只需要加入創(chuàng)建代碼即可构眯,使用部分岔冀,需要?jiǎng)h除之前頂點(diǎn)的指定方式,換成這個(gè)調(diào)用方法即可坯墨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市病往,隨后出現(xiàn)的幾起案子捣染,更是在濱河造成了極大的恐慌,老刑警劉巖停巷,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耍攘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡畔勤,警方通過查閱死者的電腦和手機(jī)蕾各,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來庆揪,“玉大人式曲,你說我怎么就攤上這事「组唬” “怎么了吝羞?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵兰伤,是天一觀的道長。 經(jīng)常有香客問我脆贵,道長医清,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任卖氨,我火速辦了婚禮会烙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘筒捺。我一直安慰自己柏腻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布系吭。 她就那樣靜靜地躺著五嫂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肯尺。 梳的紋絲不亂的頭發(fā)上沃缘,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音则吟,去河邊找鬼槐臀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛氓仲,可吹牛的內(nèi)容都是我干的水慨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼敬扛,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼晰洒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啥箭,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤谍珊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后捉蚤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抬驴,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年缆巧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了布持。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陕悬,死狀恐怖题暖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤胧卤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布唯绍,位于F島的核電站,受9級(jí)特大地震影響枝誊,放射性物質(zhì)發(fā)生泄漏况芒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一叶撒、第九天 我趴在偏房一處隱蔽的房頂上張望绝骚。 院中可真熱鬧,春花似錦祠够、人聲如沸压汪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽止剖。三九已至,卻和暖如春落君,著一層夾襖步出監(jiān)牢的瞬間穿香,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工绎速, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扔水,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓朝氓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親主届。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赵哲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容