原文地址 http://www.songho.ca/opengl/gl_vbo.html。
网上讲VBO的太多,但大部分都讲不到点子上,这篇文章是目前为止发现对VBO解释最为清晰的了,因此翻译以备复习。
OpenGL Vertex Buffer Object (VBO)
GL_ARB_vertex_buffer_object扩展意图通过提供 vertex array 和display list 来加强OpenGL的性能,同时避免了它们的实现的缺点。Vertex buffer object (VBO) 允许vertex array data存储在服务端的高性能图形内存中,并提升高效的数据传输。如果一个buffer object是用来存储pixel data,它叫做Pixel Buffer Object(PBO).
使用vertex array可以减少函数调用的次数和对共享顶点的多余使用。然而,vertex array的缺点是,vertex array functions处于客户端状态,在arrays中的数据,在每次被引用的时候,必须重新发送到服务端。
另一方面, display list是服务端的功能,因此它不会遭受数据传输的溢出。但是,一旦一个display list被编译,在display list中的数据不能被修改。
Vertex buffer object (VBO) ,为在服务端的 high-performance memory 中的 vertex attributes 创建"buffer objects”,并提供相同的访问函数来引用这些arrays,这些arrays就是在vertex arrays中使用的,如glVertexPointer(), glNormalPointer(), glTexCoordPointer(), etc.
vertex buffer object的内存管理把buffer objects放到内存中最好的位置,基于用户的指示: "target" and "usage" mode.因此内存管理可以通过平衡system, AGP and video memory三种类型的内存来优化缓存。
不同于display lists,vertex buffer object的数据可以通过把buffer映射到客户端的内存空间来实现读和更新操作。
VBO的另一个重要的优点是在多个客户端共享buffer objects,正如display lists and textures。因为VBO在服务端,多个客户端有能力通过响应的标识访问相同的buffer。
后面的是API的讲解,不多翻译了,下面翻译一下glMapBuffer。
更新VBO
VBO相对于display list的优点是可以在客户端读取和修改buffer object data,而display list 不行。更新VBO最简单的方式是通过glBufferData() or glBufferSubData()再一次把新的数据拷贝到绑定的VBO上。对于这种情况,你的应用程序的所有时间都必须有一个可用的vertex array。这意味着你必须一直有vertex data的两份拷贝:一个在你的应用中,一个在VBO中。
另一种改变buffer object的方式是映射buffer object到客户端的内存,并且客户端可以用指向mapped buffer的指针来更新数据。接下来描述如何映射VBO到客户端的内存,以及如何访问mapped data。
注意glMapBuffer()会引起同步问题。如果GPU仍然对该buffer object工作,glMapBuffer()将不会返回,直到GPU完成它对该buffer object的工作。
为了避免等待,你可以首先以参数NULL pointer调用glBufferData(),然后调用glMapBuffer()。在这种情况下,之前的数据将被抛弃,glMapBuffer()立即返回一个新的申请的指针,即使GPU仍然在之前的data上工作。
然而,这个方法只有在你想更新整个数据时才有用,因为你丢弃了之前的数据。如果你只想改变数据的一部分或者读取数据,你最好不要释放之前的数据。
在修改了VBO的数据后,必须要在客户端unmapped the buffer object。glUnmapBuffer() 成功的时候返回GL_TRUE。如果它返回GL_FALSE,VBO的内容在buffer was mapped时变成损坏的。这种损坏可能来自于屏幕分辨率的改变,或者窗口系统的特殊事件。在这种情况下,数据必须重新提交。
网友评论