原文地址http://www.ozone3d.net/tutorials/opengl_vbo.php
By Christophe [Groove] Riccio - www.g-truc.net
And
Jerome [JeGX] Guinot - jegx[NO-SPAM-THANKS]@ozone3d.net
Initial draft: May 1, 2006
Last Update: January 7, 2007
Introduction
![](https://i-blog.csdnimg.cn/blog_migrate/6ebdf7f407fbed2616485f99e80635cd.gif)
Vertex buffer object (VBO) is a new method used to describe geometric primitives. It had been introduced by NV_vertex_array_range and ATI_vertex_array_object extensions promoted to ARB_vertex_buffer_object and finally integrated into the OpenGL 1.5 specification. VBO should be the only way to describe geometric primitives with OpenGL LM.
OpenGL LM is the ARB project about simplification of OpenGL API in order to ease graphics card drivers optimisations. Its goal is to compete with Direct Graphics in the field of video games and it should be based on OpenGL 3.0 specifications. ARB aims to simplify OpenGL API which was expected by many developers for OpenGL 2.0. As a result, some features should disappear, such as immediate mode, vertex arrays and specific cases like glRect as well .
VBOs are supported by hardware featuring OpenGL 1.5 or the ARB_vertex_buffer_object extension, which is the case for the nVidia TNT series and the first ATI Radeon video controllers. However, all features aren’t always available and even some of them are not even supported by any of the actual graphic controllers.
Features, efficiency and longevity are three reasons to use VBOs as soon as possible.
![](https://i-blog.csdnimg.cn/blog_migrate/6ebdf7f407fbed2616485f99e80635cd.gif)
1.1 - OpenGL Legacy
OpenGL beginners like its simplicity through the immediate mode that comes with OpenGL 1.0. This mode looks like this:
glBegin(GL_QUADS); glColor3f(1.0f, 0.5f, 0.0f); glVertex2f(0.0f, 0.0f); glVertex2f(1.0f, 0.0f); glVertex2f(1.0f, 1.0f); glVertex2f(0.0f, 1.0f); glEnd();
This code is quiet easy to understand but it could become very slow whether the goal is to describe complex geometric primitive composed by thousand of vertices just because of the high number of function calls.
以上代码很容易理解,但是由于需要大量函数调用,使得在描述由数千顶点组成的复杂几何图元时,程序运行的非常缓慢。
OpenGL 1.1 includes vertex arrays that allow rendering a large amount of data with few function calls. This mode looks like this:
OpenGL1.1版本引入了顶点数组,使得我们render大量数据时只要调用少数函数即可。这个mode是这样的:
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); float ColorArray[] = {…}; float VertexArray[] = {…}; glColorPointer(3, GL_FLOAT, 0, ColorArray); glVertexPointer(3, GL_FLOAT, 0, VertexArray); glDrawArrays(GL_TRIANGLES, 0, sizeof(VertexArray) / sizeof(float)); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
Vertex buffer objects are similar in their principles but they provide a lot of improvements.
VBO与他们有同样的principle但是vbo有更多的改进。
1.2 - VBOs Interests
VBO provides three data transfer modes instead of one for vertex arrays.
The first one, called GL_STREAM_DRAW provides the same behaviours than vertex arrays witch means that data are sent for each call to glDrawArrays, glDrawElements, glDrawRangeElements (EXT_draw_range_elements, OpenGL 1.2) glMultiDrawArrays or glMultiDrawElements (EXT_multi_draw_array, OpenGL 1.4). This mode is particularly efficient for CPU animated objects such as characters for example.
第一个,称为GL_STREAM_DRAW,它提供了与顶点数组同样的行为:数据被送到以下函数调用,glDrawArrays, glDrawElements, glDrawRangeElements, glMultiDrawArrays or glMultiDrawElements. 这种模式在CPU animate objects时,如字符,尤其有效。
A second mode, called GL_STATIC_DRAW, inherits of features from the EXT_compiled_vertex_array extension. It allows sending vertices information only once to the graphics card because these data are saved in the graphic controller memory. This mode is suitable for non deformable objects that are to say for all geometries which remains unchanged during several frames. This mode is the one which could provide the highest performances as the memory is reserved and the graphic controller's bandwidth is much larger thant the one of the CPU.
第二个模式,称为GL_STATIC_DRAW,从 EXT_compiled_vertex_array extension继承了许多功能。由于数据被保存在graphic controller memory中,它允许将顶点信息只发送一次到显卡。这种模式适合于不易变形的物体,也就是在许多帧刷新后几何信息仍然不变的物体。当图形controller的带宽比CPU的带宽宽很多,而且memory is reserved 时,这种模式能提供最高性能。
The last mode is GL_DYNAMIC_DRAW. With this mode, the graphics drivers will choose the data location. This mode is recommended for animated object that are rendered several times per frame, for example in case of multi passes rendering.
最后一个模式成为GL_DYNAMIC_DRAW。使用这种模式,图形drivers将会选择数据location.这种模式适合于动态这种每一frame要render很多遍的类型,比如多通道渲染(multi passes rendering) .
To summarize, use these modes:
- GL_STREAM_DRAW when vertices data could be updated between each rendering.
- GL_DYNAMIC_DRAW when vertices data could be updated between each frames.
- GL_STATIC_DRAW when vertices data are never or almost never updated.
总结来说:
GL_STREAM_DRAW:在每个redering之间数据需要更新。
GL_DYNAMIC_DRAW:在每个frames之间数据需要更新。
GL_STATIC_DRAW:数据从不更新或几何不更新。
Notice that these three modes are more and more considered by the graphics drivers as a recommendation. Therefore, sometimes they may not pay attention to your advice and choose on their own. Consequently, it could happen that you don’t observe any frame rate variation when you are toggling modes.
The second improvement that characterise VBOs is called Vertex mapping. It represents the ability of not using a temporary array to store vertices data. Instead, an array, which is allocated by OpenGL, is directly used for storing this data. Notice that VBOs are also available with OpenGL ES 2.0 but this feature is optional. This feature appeared with ATI_map_buffer_object extension which is available since the first ATI Radeon. nVidia has also provided an extension for this feature which is called NV_vertex_array_range. However, the memory allocation is manually done using the OpenGL context… With VBOs this allocation is transparent.
第二个改进称为vertex mapping。它意味着不使用临时数组存储数据的能力。opengl直接使用一个数组来存储这些数据。VBO在OGLES2.0版本可以使用,但这种feature并非强制的。自从第一个ATI速龙显卡出现,这种feature就伴随着 ATI_map_buffer_object extension同时出现。nVidia同样提供了这种extension,称为NV_vertex_array_range。但是,内存allocation需要通过使用OpenGL context手工进行...With VBOs 这种allocation是透明的。
Finally, VBOs provide an excellent alternative to interleaved arrays. As a recall, interleaved arrays allow sending vertices data to the graphics card by using a single array described by the glInterleavedArrays function. With vertex arrays, we had to use predefined data structures with a precise order for each element of that structure. With the GPU programming arising, the customized programmer attributes are not handled anymore. VBOs solve this issue and allow to update only a part of the data.
最后VBO为 interleaved 数组提供了一个极棒的选择。As a recall,interleaved 数组允许通过使用被 glInterleavedArrays函数描述的,一个单一的数组,将顶点数据发送到显卡。当GPU编程越来越火,customized programmer attributes are not handled anymore. VBOs解决了这一难题,允许更新数据的一部分。
1.3. Partial support
VBOs provide a robust API that matches all needs of current and future graphics cards. Thus, they provide six other transfer modes called GL_STREAM_READ, GL_STREAM_COPY, GL_DYNAMIC_READ, GL_DYNAMIC_COPY, GL_STATIC_READ and GL_STATIC_COPY.
VBOs 提供了一个robust的API来适应如今和将来各种显卡的需求。因而,他们提供六个其他的转换模式:GL_STREAM_READ, GL_STREAM_COPY, GL_DYNAMIC_READ, GL_DYNAMIC_COPY, GL_STATIC_READ and GL_STATIC_COPY.
Unfortunately, it seems to me that none of the current graphics card is supporting these features for the moment. The ATI Render to Vertex Buffer (R2VB) technology featured by Radeon X1*00 nearly matches the functionnalities provided by this six modes. However, ATI did not communicate any information regarding the OpenGL aspect of this topic, but it looks pretty much like Pixel Buffer Object (ARB_pixel_buffer_object) so it doesn’t bring anything new for OpenGL.
不幸的是,对我来说现如今没有显卡支持这些features。ATI的RadeonX100显卡的R2VB工艺几乎match了这六种模式提供的功能。但是ATI没有向OpenGL方面传递任何关于这个主题的信息,但是它看起来像PBO一样pretty,所以它没有为OpenGL带来任何新东西。
Modes finishing with GL_*_READ allow reading any data handled by OpenGL. Rules on GL_STREAM_*, GL_DYNAMIC_* and GL_STATIC_* terms are the same but they now refer to the number of data reading performed by the program. Modes using the term GL_*_COPY allow to display a geometry from a source managed by OpenGL.
以GL_*_READ 结束的模式允许读取由OpenGL handle的任何数据。GL_STREAM_*, GL_DYNAMIC_* and GL_STATIC_*有同样的规则,but they now refer to the number of data reading performed by the program.使用GL_*_COPY的模式允许显示一个由OpenGL管理的source的几何体。
In concrete terms, what are these modes used for? For the upcoming graphics card generations, known as the G80 for nVidia and R600 for ATI, new features will be available. They are brought into disrepute under DirectX names like Shader Model 4.
![DirectX 10 Graphics Pipeline DirectX 10 Graphics Pipeline](https://i-blog.csdnimg.cn/blog_migrate/8d101156fa74fe4f52202ca6d30230d0.gif)
Picture from DirectX 10 documentation that represents the graphic pipeline
Geometry shaders, called primitive shaders in OpenGL, will allow vertices instancing from the GPU. As the previous figure shows, the graphic pipeline will change by allowing data transfer, here refered as the “stream output stage”. This stream of data requires an API, and the VBOs' GL_*_COPY and GL_*_READ modes are specially designed to answer this need. GL_*_COPY modes seems suitable for handling recursive processing on vertices, which could dramatically increase resources required by the vertex pipelines. The marketing action by ATI with R2VB is based on an analogy with this new “stream output stage” using pixels as stream output. However there is no way for pixel creation with Radeon X1*00.