【OpenGL ES】關於VBO(Vertex Buffer Object)的一些坑——解析一些關於glBuffer的函數


最近在寫畢設的時候用到OpenGL ES中的VBO,由於對一些接口用到的變量不了解被坑得很慘,在此記錄一下防止以后再被坑。

本文為大便一籮筐的原創內容,轉載請注明出處,謝謝:http://www.cnblogs.com/dbylk/p/4492306.html 

 


 

使用VBO的好處在此就不多說了,在Java中操作VBO繪圖涉及到的OpenGL接口主要有以下幾個:

1. void glGenBuffers(int n, int[] buffers, int offset)

向OpenGL ES申請開辟新的VBO,並通過buffers數組獲取VBO handle,handle的類型為整型。

int n      申請的VBO個數

int[] buffers  用於存儲VBO handle的數組

int offset    buffers數組的偏移量,即從buffers的第offset個位置開始存儲handle

注意需要滿足 n + offset <= buffers.length

 

2. void glBindBuffer(int target, int buffer)

通過handle綁定指定的VBO,同一時間只能綁定一個同類型的VBO,只有當前被綁定的VBO才會被用戶操作。通過綁定handle為0的VBO,可以取消對所有同類型VBO的綁定。

int target    指定綁定的VBO類型,具體類型有GL_ARRAY_BUFFER(用於為頂點數組傳值)和GL_ELEMENT_ARRAY_BUFFER(用於為索引數組傳值)

int buffer    指定綁定的VBO handle

 

3. void glBufferData(int target, int size, Buffer data, int usage)

將數據傳遞給當前綁定的VBO。

int target    指定VBO類型,同上

int size      指定VBO的大小,單位為byte

Buffer data   指定需要傳遞的數據

int usage    指定VBO的存儲方式,例如GL_STATIC_DRAW或GL_DYNAMIC_DRAW

 

4. void glVertexAttribPointer(int indx, int size, int type, boolean normalized, int stride, int offset)

將VBO中的數據傳遞給頂點數組。

int indx           指定Shader屬性的頂點數組handle

int size        指定該屬性的頂點數組大小,單位為數組元素的類型

int type         指定該屬性的頂點數組元素類型,如GL_FLOAT和GL_UNSIGNED_BYTE

boolean normalize  指定傳遞給該屬性頂點數組的數據是否需要歸一化(轉化為單位向量)

int stride       指定該屬性的頂點數據在VBO中的躍度,即每個頂點所占的數據長度,單位為byte

int offset       指定該屬性在VBO中起始位置的偏移量,單位為byte

 

5. void glDrawArrays(int mode, int first, int count)

直接使用頂點數組繪制圖元。

int mode    指定繪圖的模式,如GL_TRIANGLES和GL_TRIANGLE_STRIP

int first     指定從第幾個頂點開始繪制

int count    指定繪制幾個頂點

本人博客地址,防止無腦抄襲,影響閱讀見諒:http://www.cnblogs.com/dbylk

 

6. void glDrawElements(int mode, int count, int type, int offset)

使用索引數組繪制圖元。

int mode    指定繪圖的模式,如GL_TRIANGLES和GL_TRIANGLE_STRIP

int count    指定繪制幾個頂點

int type      指定索引數組的數據類型,如GL_UNSIGNED_SHORT和GL_UNSIGNED_INT

int offset      指定索引數組起始位置的偏移量,單位為byte 

 

通過下面的簡單實例中可以了解這些方法在實際操作中如何使用:

// Author DaBianYiLuoKuang.
// http://www.cnblogs.com/dbylk/

public void onDrawFrame(GL10 gl) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        
    // 設置旋轉矩陣的函數,在此可以忽略
    setRotationView(0);
        
    // 獲取Position屬性的location
    int positionHandle = GLES20.glGetAttribLocation(programHandle, "Position");
    // 獲取SourceColor屬性的location
    int colorHandle = GLES20.glGetAttribLocation(programHandle, "SourceColor");

    // 激活兩個屬性的數組
    GLES20.glEnableVertexAttribArray(positionHandle);
    GLES20.glEnableVertexAttribArray(colorHandle);

    // 每個頂點的躍度,即一個頂點占有的數據類型個數
    int stride = 6;
    // 頂點數據數組,6個float組成一個頂點,前2個float為位置坐標,后4個float為顏色RGBA
    float[] data = {
        -0.5f, -0.5f,        1f, 1f, 1f, 1f,
         0.5f, -0.5f,        1f, 1f, 1f, 1f,
           0f,    1f,        1f, 1f, 1f, 1f
    };
        
    // 將頂點數組封裝進Buffer中
    // 值得注意的一點是通過Buffer.wrap()方法生成的Buffer無法在OpenGL ES中使用,必須通過如下方法創建Buffer
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4);
    // OpenGL ES中使用的數據為小端字節序(低位字節在前,高位字節在后),而Java的Buffer默認使用大端字節序(高位字節在前,低位字節在后)存儲數據,所以在此需要通過下面的方法進行轉換
    byteBuffer.order(ByteOrder.nativeOrder());
    // 將ByteBuffer轉換為FloatBuffer
    FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
    // 將data中的數據放入FloatBuffer中
    floatBuffer.put(data);
    // 重新定義Buffer的起點和終點,等價於同時使用postion(0)方法和limit(data.length)方法
    floatBuffer.flip();
        
    // 用於獲取VBO handle的臨時變量
    int[] temp = new int[1];
    // 向OpenGL申請新的VBO,將handle存於temp中
    GLES20.glGenBuffers(1, temp, 0);
    // 從temp中取出VBO handle
    vertexBufferHandle = temp[0];
    // 綁定剛剛申請到的VBO
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferHandle);
    // 將FLoatBuffer中的數據傳遞給OpenGL ES
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, floatBuffer.limit() * 4, floatBuffer, GLES20.GL_STATIC_DRAW);

    // 將VBO中的數據傳遞給shader中的頂點數組
    GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, stride * 4, 0);
    GLES20.glVertexAttribPointer(colorHandle,    4, GLES20.GL_FLOAT, false, stride * 4, 2 * 4);

    // 繪制三角形
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

    // 取消buffer的綁定
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    
    // 反激活頂點數組
    GLES20.glDisableVertexAttribArray(positionSlot);
    GLES20.glDisableVertexAttribArray(colorSlot);
} 

 

關於注釋中提到的大端字節序和小端字節序,具體可以查閱下篇博文:

http://www.cnblogs.com/xiehy/archive/2010/11/25/1887779.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM