OpenGL Vertex Cache Object

Source: Internet
Author: User
Tags bind strlen

Vertex cache Objects (Vertex buffer object, referred to as VBO), allow developers to place vertex data in memory as appropriate.

If you do not need to VBO, use Glvertexpointer/glnormalpointer to specify the vertex data, the vertex data is placed in the system memory, each time you render, you need to copy the data from the system memory to video memory, consumes a lot of time.

In fact, many copies are unnecessary, such as the static object vertex data is constant, if you can put them into the video memory, then each render without the need for copy operation, can save a lot of time. 1. Check for extensions

Gl_arb_vertex_buffer_object, is an OpenGL extension, also known as VBO.

To use this extension, first detect whether the current OpenGL version supports this extension. Write a function that can be used to check any extension, and the argument is a string with the extension.

int checkextension (char *extname)
{
    char *p = (char *) glgetstring (gl_extensions);
    char *end;
    int extnamelen = (int) strlen (extname);

    End = p + strlen (p);
    while (P < end) {
        int n = (int) strcspn (P, "");
        if ((Extnamelen = = N) && (strncmp (Extname, p, n) = = 0) {
            return TRUE;
        }
        p + = (n + 1);
    }
    return FALSE;
}

Then, call Checkextension to detect if the extension exists and the extension is gl_arb_vertex_buffer_object. If the extension exists, then call wglgetprocaddress to get a pointer to the required extension function, respectively. For example: Glgenbuffers, Glbindbuffer.

Sometimes a name such as Glgenbuffersarb is used to indicate that the function is in the extension library. In older versions of OpenGL, the new version of OpenGL used Glgenbuffers to remove the ARB.

if (Checkextension ("Gl_arb_vertex_buffer_object"))
{
    glgenbuffers = (pfnglgenbuffersarbproc) Wglgetprocaddress ("Glgenbuffersarb");
    Glbindbuffer = (Pfnglbindbufferarbproc) wglgetprocaddress ("Glbindbufferarb");
    Glbufferdata = (Pfnglbufferdataarbproc) wglgetprocaddress ("Glbufferdataarb");
    Glbuffersubdata = (Pfnglbuffersubdataarbproc) wglgetprocaddress ("Glbuffersubdataarb");
    Gldeletebuffers = (Pfngldeletebuffersarbproc) wglgetprocaddress ("Gldeletebuffersarb");
}
else
{
    cout<< "error:gl_arb_vertex_buffer_object extension is not found" <<endl;
    return FALSE;
}
2. Create a vertex cache object

Building a VBO requires three steps: Creating a Cache object, using glgenbuffers () to bind the cache object (specifying which cache object to use), using glbindbuffer () to copy the vertex data to the cache object, using the Glbufferdata ()

An introduction to the three functions is as follows.

void Glgenbuffers (Glsizei N, gluint* ids)

Creates a cache object and returns an identifier for the cached object. N-The number of cache objects created. IDS-is a variable or array of type Gluint that stores a single ID or multiple IDs of cached objects.

void Glbindbuffer (Glenum target, gluint ID)

Once the cache object has been created, we need to bind the cache object for use. A binding that specifies which cache object is currently being used.

Target-the data type to be stored by the cache object, with only two values: Gl_array_buffer, and Gl_element_array_buffer. If it is a vertex related property, for example: vertex coordinates, texture coordinates, normal vector, color array, etc., to use Gl_array_buffer; index array, to use gl_element_array_buffer so that gldrawelements () use.

ID-The ID of the cached object.

void Glbufferdata (glenum target, Glsizei size, const void* data, Glenum usage)

Copy the data to the cached object. Target-the type of the cached object, with only two values: Gl_array_buffer and Gl_element_array_buffer. Size-The amount of data in the array, in bytes (bytes). Data-A pointer to the array data, and if NULL is specified, VBO only creates a cache object of the corresponding size. Usage-How the cached object is used, there are three: static, dynamic, and stream. A total of 9 values:

Gl_static_draw
gl_static_read
gl_static_copy
gl_dynamic_draw
gl_dynamic_read
gl_dynamic_ COPY
gl_stream_draw
gl_stream_read
gl_stream_copy

The old version of OpenGL will add ARB to form a shape like gl_static_draw_arb. Static refers to the data in the cached object cannot be changed (set once, use many times). Dynamic means that data will be changed frequently (repeatedly set and used). Stream means that every frame of data is changed (set once, use once). Draw refers to the data that will be sent to the GPU for plotting (application to GL). Read refers to the data that will be read to the client application (GL to application). Copy means that the data will be used for drawing and reading (GL to GL).

Note that Draw is only useful for VBO, and Copy and read are only meaningful for PBO (pixel cache objects) and FBO (frame cache objects).

The VBO memory manager chooses the appropriate storage location based on the tag.

void Glbuffersubdata (glenum target, glint offset, glsizei size, void* data)

As with Glbufferdata (), it is used to copy data to the cached object. It can copy a piece of data to an already existing cache , offset by offsets.

void Gldeletebuffers (glsizei n, const gluint* IDs)

Deletes one or more cached objects. 3. Use of vertex caches and index caches

There are data as follows:

Glfloat vertexs[] = {0.0f, 0.0f, 0.0f, 0.2f, 0.0f, 0.0f,
                     -0.2f, 0.0f, 0.0f, 0.0f, 0.2f, 0.0f,
                     0.0f, -0.2f, 0.0f, 0.0f, 0.0f, 0.2f,
                     0.0f, 0.0f, -0.2f};

Glubyte indexs[] = {0,1,2,3,4,5,6};

Generate the Cache object and copy the data.

Gluint Vbovertexid;
Gluint Vboindexid;

Glgenbuffers (1, &VBOVERTEXID);
Glbindbuffer (Gl_array_buffer, VBOVERTEXID);
Glbufferdata (Gl_array_buffer, sizeof (VERTEXS), Vertexs, Gl_static_draw);

Glgenbuffers (1, &VBOINDEXID);
Glbindbuffer (Gl_element_array_buffer, VBOINDEXID);
Glbufferdata (Gl_element_array_buffer, sizeof (INDEXS), Indexs, Gl_static_draw);

Then, when using, add the following code.

Glenableclientstate (Gl_vertex_array);
Glenableclientstate (Gl_index_array);

Glbindbuffer (Gl_array_buffer, VBOVERTEXID);
Glvertexpointer (3, gl_float, 0, 0);

Glbindbuffer (Gl_element_array_buffer, VBOINDEXID);
Glindexpointer (gl_unsigned_byte, 0, 0);

...//Draw graphics

gldisableclientstate (gl_vertex_array); 
Gldisableclientstate (Gl_index_array);
Glbindbuffer (gl_array_buffer, 0);

There are three ways to use cached objects:

1. The first kind of
glbegin (gl_points);
    Glarrayelement (0);
    Glarrayelement (1);
    Glarrayelement (2);
    Glarrayelement (5);
Glend ();

2. The second type of
gldrawelements (gl_points, 7, gl_unsigned_byte, 0);

3. The third Kind of
gldrawarrays (gl_points,0,7);
4. Copying different types of data to a cache object

You can copy several data to a cache object using Glbuffersubdata (). For example, you have the following data:

Glfloat vertexs[] = {0.0f, 0.0f, 0.0f, 0.2f, 0.0f, 0.0f,
                    -0.2f, 0.0f, 0.0f, 0.0f, 0.2f, 0.0f,
                    0.0f, -0.2f, 0.0f, 0.0f, 0.0f, 0.2f,
                    0.0f, 0.0f, -0.2f};

Glfloat colors[] = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                    0.0f, 1.0f, 1.0f, 1 .0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 0.0f};

Now, to have two arrays in the same cache object, the vertex array is in front, and the color array is behind. The code is as follows:

Glgenbuffers (1, &VBOVERTEXID);
Glbindbuffer (Gl_array_buffer, VBOVERTEXID);
Glbufferdata (Gl_array_buffer, sizeof (VERTEXS) +sizeof (colors), 0, Gl_static_draw);
Glbuffersubdata (gl_array_buffer, 0, sizeof (VERTEXS), vertexs);     Note the third parameter, offset
glbuffersubdata (gl_array_buffer, sizeof (VERTEXS), sizeof (colors), colors);

After creating the cache object, specify the appropriate pointer position with Glvertexpointer and Glcolorpointer. However, because of the last parameter of Glcolorpointer, it must be a pointer type. Take a look at the following code, where the last parameter of Glcolorpointer indicates the position of the color array with an offset.

Glenableclientstate (Gl_vertex_array);
Glenableclientstate (Gl_color_array);
Glenableclientstate (Gl_index_array);

Glbindbuffer (Gl_array_buffer, VBOVERTEXID);
Glvertexpointer (3, gl_float, 0, 0);
Glcolorpointer (3,gl_float,0, (void*) sizeof (VERTEXS));    Note the last parameter

glbindbuffer (Gl_element_array_buffer, VBOINDEXID);
Glindexpointer (gl_unsigned_byte, 0, 0);

Gldrawarrays (gl_points,0,7);

Gldisableclientstate (Gl_vertex_array); 
Gldisableclientstate (Gl_color_array); 
Gldisableclientstate (Gl_index_array);
Glbindbuffer (gl_array_buffer, 0);
5. Modifying cached Objects

VBO a great advantage over display lists is the ability to read and modify data from cached objects. The simplest method is to re-copy the data to VBO, using Glbufferdata () and Glbuffersubdata (), in which case your program must have two copies of the data: one on the client (CPU), one on the device side (GPU).

Another way to do this is to map the cached object to the client and then modify the data through the pointer.

void* Glmapbuffer (glenum target, glenum access)

Mapping the currently bound cache object to the client, Glmapbuffer returns a pointer to the cache object. If OpenGL is not supported, NULL is returned. Target-gl_array_buffer or Gl_element_array_buffer. Access-has a value of three gl_read_only, Gl_write_only, and Gl_read_write, which represent read-only, write-only, and read-writable.

If OpenGL is manipulating the cache object, this function will not succeed until OpenGL processing is complete. To avoid waiting, you can use Glbindbuffer (gl_array_buffer, 0) to stop the application of the cached object before calling Glmapbuffer.

Glboolean Glunmapbuffer (glenum target)

After modifying the data, map the data back to the device side.

See the following code for the usage method.

Glbindbuffer (Gl_array_buffer, VBOVERTEXID);
glfloat* ptr = (float*) glmapbuffer (Gl_array_buffer, gl_write_only);

if (PTR)
{
    ptr[0] = 0.2f;  PTR[1] = 0.2f;  PTR[2] = 0.2f;
    Glunmapbuffer (Gl_array_buffer);
}

Glbindbuffer (gl_array_buffer, 0);
References

[1] About Gl_arb_vertex_buffer_object extensions

[2] OpenGL Vertex Buffer Object (VBO)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.