zoukankan      html  css  js  c++  java
  • 【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

     

  • 相关阅读:
    vue typescript: Parameter ‘XXX’ implicitly has an ‘any’ type.解决方法
    ESLint学习(一)简介、安装、配置、命令行、规则
    使用vite搭建vue3项目(三) 配置国际化
    VUE3+Typescript 引用process提示错误
    centos7安装vsftpd,配置
    使用vite搭建vue3项目(一) 创建一个工程
    Symbols 是 JavaScript 最新推出的一种基本类型
    使用vite搭建vue3项目(二) 引入vuerouter
    在使用vite时使用import.meta.globEager 代替 require.context 自动导入文件
    VUE3.X版本error: Parsing error: Parsing error: Unexpected token 的解决办法
  • 原文地址:https://www.cnblogs.com/dbylk/p/4492306.html
Copyright © 2011-2022 走看看