您的位置:首页 > 运维架构

opengl缓冲区对象

2015-12-24 23:41 344 查看
转自 http://iqnix.blog.163.com/blog/static/21721982014228115223718/

一:为什么要有opengl缓冲区对象

前面的顶点数组使得几何图元的显示方便了很多,但是如果每次都要向OPENGL发送一大块数据,而这数据其实并没有修改过,那么传输就是冗余的。所以这里添加了缓冲区对象,将顶点数组存储在服务器端的缓冲区对象中。

二:如何创建和使用缓冲区对象

1.创建缓冲区对象

    glGenBuffers():OpenGL分配n个当前未使用的名称(非 0),表示缓冲区对象。

    原型 : void glGenBuffers(GLsizei n,GLuint *buffers);

    GLboolean glIsBuffer(GLuint buffer):判断一个标识符是否是当前使用的缓冲区对象的标识符。

  2.激活缓冲区对象

    激活缓冲区对象,首先需要对他进行绑定。绑定缓冲区对象表示选择未来的操作将影响到哪个缓冲区    对象。

    glBindBuffer(GLenum target ,GLuint buffer): 指定了当前的活动缓冲区对象 。

  3.用数据分配和初始化缓冲区对象

     一旦绑定了一个缓冲区对象,就需要保留空间以存储数据。

    void glBufferData(GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage );

    功能是分配size个存储单位的OpenGL服务器内存,用于存储顶点数据或索引。以前有与当前缓冲区对象相关联的数据将删除。

    glBufferData()首先在OpenGL拂去其中分配内存以存储数据。如果成功分配,data!=NULL,size个单位就会从客户机内存复制到这个对象中。如果data=NULL,为数据保留适当的空间,但不会初始化。

4.更新缓冲区对象的数据值

    方法一:假设已经在用用程序的一个缓冲区中准备了相同类型的数据,glBufferSubData()将用我们提供的数据替换被绑定的缓冲区对象的一些数据子集。

            void glBufferSubData(GLenum target,GLuint offset,GLsizei size,const GLvoid *data); 用data 指向的数据更新 与target 相关联的当前绑定缓冲区对象中从offset开始的size个字节数据。

             

    方法二:允许灵活的选择需要更新的数据。

            GLvoid *glMapBuffer(GLenum target,GLuenum access):返回一个指向缓冲区对象的指针,可以在这个缓冲区对象中写入新值及更新之后,再调用GLboolean glUnMapBuffer(GLenum target)表示已经完成了对数据的更新,取消对这个缓冲区的映射。如果只需要更新所需范围内的数据值,也可调用GLvoid *glMapBuffwerRange(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield
access)

   5.在缓冲区对象之间复制数据

     void glCopyBufferSubData(readbuffer,writebuffer,resdoffset,writeoffset,size);

     把数据从与readbuffer相关联的缓冲区对象复制到绑定到writebuffer的缓冲区对象。

   6. 清除缓冲区对象

      glDeleteBuffer(GLsizei n,const GLuint *buffers):删除n个缓冲区对象。被删除的当前缓冲区对象的所有绑定都重置为零。如果一个缓冲区对象是在绑定时删除的,这个对象的所有绑定都重置为默认的缓冲区对象。

   7.使用缓冲区对象来存储顶点数组数据

      需要以下步骤:

       (1)生成缓冲区对象标识符;

       (2)绑定缓冲区对象,确定是存储顶点数据还是索引;

       (3)请求数据的存储空间,并对数据元素进行初始化;

       (4)指定相对于缓冲区起始位置的偏移量;

       (5)绑定适当的缓冲区对象,用于渲染;

       (6)使用适当的顶点数组渲染函数进行渲染,比如glDrawArrays()

      如果想初始化多个缓冲区对象,就需要为每个缓冲区对象重复以上。顶点数组数据的所有格式都适用于缓冲区对象。

转自:http://blog.csdn.net/bugrunner/article/details/5356781

OpenGL的缓冲对象提供了一种高效的数据操作及吞吐方式,这此操作涉及整个渲染管线的多个环节,用来提高OpenGL的实现效率。常见的缓冲对象有:顶点缓冲对象(VBO)、像素缓冲对象(PBO)和帧缓冲对象(FBO),各种缓冲对象的操作方式及应用场合不尽相同,但主要都是在关系到内存与显存之间需进行数据传输与交互时而进行的优化操作,因为内存与显存之间的数据交互在当前的硬件渲染架构下是必须的,但效率却又受限于PCI的传输速度。缓冲区对象的作用就是让这种数据交互操作在一种最优的方式下进行,使所有的操作从Client到显存之间的距离尽可能地缩短,从而提高效率。

Vertex Buffer Object:
1.      在Client与Server之间快速地操作几何顶点数据,能够很快地对顶点数据进行更新等操作。这里顶点数据的实质可以根据具体需要以其它数据填充。
2.      开辟的实际数据空间的位置不确定,根据VBO的属性及CPU调用的次数,由显存逐渐向内存转移。
 
Pixel Buffer Object:
1.      在Client与Server之间快速地操作各类像素数据
2.      高效并不在于传输更快,而在于与硬件相关的异步调用方式,调用之后CPU即返回执行其它操作(使用DMA方式的传输、由OpenGL直接控制)
3.      在单个PBO情况下并不能得到很好的效果,毕竟传输过程仍然存在(但速度可能变快,比如显存内部的数据传输),但其异步性就提供了双PBO实现的可能性,用双PBO来进行加速。
4.      PBO关联的实际数据空间位置不确定,主要由PBO的属性及OpenGL来确定。
 
Frame Buffer Object:
1.      提供了一个与FrameBuffer同类型的离屏渲染操作对象,可直接控制管线最终数据的去向。
2.      分配的空间是在显存之中,因此用FBO来对显存进行涉及GPU运算的交互操作效率较高。
3.      主要用于显存内部数据的转化、交互、操作的场合?

 
整个过程可用如下图所示:
 


 
注意:所有的Buffer Object都只是一个中间的管理平台,与实际的空间相分离。其中,除了FBO所关联的数据空间在显存之外,PBO和VBO所关联的数据空间位置均不一定(system memory, shared memory, AGP, Video Memory均有可能)

 
关于更加详细的Buffer Object使用方法可以参见:
《OpenGL Super Bible》(chapter11, chapter18)
http://www.songho.ca/opengl/gl_vbo.html
http://www.songho.ca/opengl/gl_pbo.html
http://www.songho.ca/opengl/gl_fbo.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: