【OpenGL ES】关于VBO(Vertex Buffer Object)的一些坑——解析一些关于glBuffer的函数

最近在写毕设的时候用到OpenGL ES中的VBO,由于对一些接口用到的变量不了解被坑得很惨,在此记录一下防止以后再被坑。



使用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的大小,单位为bytes

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中的跃度,即每个顶点所占的数据长度,单位为bytes

int offset       指定该属性在VBO中起始位置的偏移量,单位为bytes

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

直接使用顶点数组绘制图元。

int mode    指定绘图的模式,如GL_TRIANGLES和GL_TRIANGLE_STRIPS

int first     指定从第几个顶点开始绘制

int count    指定绘制几个顶点

类似功能的函数还有void glDrawElements(int mode, int count, int type, int offset),此函数通过使用索引数组绘制图元。   

通过下面的简单实例中可以了解这些方法在实际操作中如何使用:

public void onDrawFrame(GL10 gl) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    // 设置旋转矩阵的函数,在此可以忽略
    setRotationView(0);

    // 获取Position属性的句柄
    int positionHandle = GLES20.glGetAttribLocation(programHandle, "Position");
    // 获取SourceColor属性的句柄
    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

时间: 2024-08-22 11:01:54

【OpenGL ES】关于VBO(Vertex Buffer Object)的一些坑——解析一些关于glBuffer的函数的相关文章

基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)

在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object).IBO(Index Buffer Object)和MVP(Modile-View-Projection)变换. 本文将在教程4的基础之上,添加纹理贴图支持.最后,本文会把纹理贴图扩展至3D立方体上面. 基本方法 当我们把一张图片加载到内存里面之后,它是不能直接被GPU绘制出来的,纹理贴图过程如下: 首先,我们为之前的顶点添加纹理坐标属性并传到vertex shader里面去: 然后

Opengl ES 1.x NDK实例开发之五:顶点缓存VBO

开发框架介绍请参见:Opengl ES NDK实例开发之一:搭建开发框架 本章在上一章的基础上讲解顶点缓存数组(Vertex Buffer Object)即VBO的使用,使用VBO来实现金字塔和立方体的绘制,绘制的效果和上一章相同.这个系列教程主要是采用实例演示 Opengl ES 1.x NDK开发,对一些要点进行解释,因此对API的用法和说明较少,建议初学者可以参考Opengl ES 1.x的API手册. >>>为什么要使用VBO? VBO的数据存放在显卡内存中,能节省从系统内存复制

OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)

片段操作图 这篇文章将介绍从写入帧缓冲和读取帧缓冲的方式. Buffers(缓冲) OpenGL ES支持三种缓冲: OpenGL ES •• Color buffer颜色缓冲 •• Depth buffer深度缓冲 •• Stencil buffer模板缓冲 创建缓冲区 OpenGL ES 是一个交互式的渲染系统,假设每帧的开始,你希望初始化所有缓冲区中数据的默认值.调用glClear 函数来清除缓冲区内容,参数mask 指定清除的缓冲区. 你可能不要求清除每一个缓冲区,不在同时清除它们.但如

[转] iOS OpenGL ES Guide

OpenGL ES 小结 概述 OpenGL ES (Open Graphics Library for Embedded Systems)是访问类似 iPhone 和 iPad 的现代嵌入式系统的 2D 和 3D 图形加速硬件的标准. 把程序提供的几何数据转换为屏幕上的图像的过程叫做渲染. GPU 控制的缓存是高效渲染的关键.容纳几何数据的缓存定义了要渲染的点.线段和三角形. OpenGL ES 3D 的默认坐标系.顶点和矢量为几何数据的描述提供了数学基础. 渲染的结果通常保存在帧缓存中.有两

基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)

在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时,我们还会介绍VBO(顶点缓冲区对象)和VAO(顶点数组对象)的基本用法. 在编写自己的shader之前,我觉得有必要提一下OpenGL渲染管线. 理解OpenGL渲染管线,对于学习OpenGL非常重要.下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段) 此图是从wiki中拿过来的

OpenGL ES 简单教程

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库. 为桌面版本号OpenGL 的一个子集. OpenGL ES 定义了一个在移动平台上可以支持OpenGL最基本功能的精简标准.以适应如手机.PDA或其他消费者移动终端的显示系统. Khronos Group 定义和管理了OpenGL ES标准. OpenGL 与 OpenGL ES的关系OpenGL ES 是基于桌面版本号OpenGL 的

outdated: 45.Vertex Buffer Objects

这一节主要说的是VBO,而我的机子不支持,只好抄个代码,可怕......这是截图. VBO初始化时的代码, // Check for VBOs supported #ifndef NO_VBOS g_fVBOSupported = IsExtensionSupported("GL_ARB_vertex_buffer_object"); if (g_fVBOSupported) { // Get pointer glGenBuffersARB = (PFNGLGENBUFFERSARBP

【Qt for Android】OpenGL ES 绘制彩色立方体

Qt 内置对OpenGL ES的支持,选用Qt进行OpenGL ES的开发是非常方便的,许多辅助类都已经具备.从Qt 5.0开始增加了一个QWindow类,该类既可以使用OpenGL绘制3D图形,也可以使用QPainter绘制2D传统的GDI+图形,5.0以前的QGLWidget不推荐再使用.在即将到来(官方时间是今年秋天)Qt 5.4会完全废弃QGLWidget,作为替代将会新增QOpenGLWidget和QOpenGLWindow类来方便OpenGL的编程. 好了废话不多说了,今天我会使用O

Android OpenGL ES(十四)gl10方法解析

Android 支持 OpenGL 列表 1.GL 2.GL 10 3.GL 10 EXT 4.GL 11 5.GL 11 EXT 6.GL 11 ExtensionPack 我们将使用 GL10 这个类开始接触 OpenGL,探索3D 领域. javax.microedition.khronos.opengles 接口GL10 上级接口:GL 下级接口:GL11 公共接口GL10继承于GL GL10接口包含了Java(TM)程序语言为OpenGL绑定的核心功能.OES_byte_coordin