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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.