Vertex Buffer Object

advertisement
Vertex Buffer Object
Slides are adapted from:
http://www.songho.ca/opengl/gl_vbo.html
http://www.opengl.org/wiki/Vertex_Buffer_Objects
CPU/Client
Data for
rendering
Main Memory
GPU/Server
Video Memory
Host to the main application
Host to the rendering task
Rendering speed depends on how fast data (vertices and vertex
attributes) can be sent to the GPU. OpenGL tries to minimize the
number of function calls needed for data transfer and rendering
Display List
GlBegin-GlEnd pair
Vertex Array
Vertex Buffer Object
Immediate mode: using GlBegin()
and GlEnd()
What is the most basic way to render a model?
glBegin(GL_TRIANGLES);
for(int i=0; i<num_vertices*3; i=i+3)
{
glVertex3f( vertices[i], vertices[i+1], vertices[i+2] );
// Optionally other vertex attributes
glNormal3f( normals[i], normals[i+1], normals[i+2] );
}
glEnd();
Slow because of very high number of OpenGL commands issued !!
Vertex Array
•  Store vertex data in a set of arrays including vertex coordinates, normal, texture coordinates and color
information
•  Draw geometric primitives by dereferencing the array
elements with array indices.
•  Basically you need to specify (instead of writing a loop):
–  Array location
–  Primitive type
–  Number of primitives to draw
•  OpenGL v1.2 or greater needed
Vertex Array: Implementation
// array holding vertex coords
GLfloat vertices[] = {...};
In your case, this will be the
Array containing polygons of
The model
Read your model here
... // activate and specify pointer to vertex array
glEnableClientState(GL_VERTEX_ARRAY);
// and specify pointer to vertex array
glVertexPointer(3, GL_FLOAT, 0, vertices);
// draw a cube
glDrawArrays(GL_QUADS, 0, 24);
// deactivate vertex arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
Similarly, Normal Array, Color
Array etc are enabled here
Similar pointers to other arrays
Are specified here
In your case, your model
Drawing vertices with indices
May be useful since your .ply model contains vertices, and then indices
// vertex co-ords: 8 in this example
GLfloat vertices[] = {...};
// 24 of indices
GLubyte indices[] = {0,1,2,3, 0,3,4,5,
0,5,6,1, 1,6,7,2,
7,4,3,2, 4,7,6,5};
... // activate and specify pointer to vertex array
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, indices);
// deactivate vertex arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
Display List
•  Group of OpenGL commands stored (compiled) for later
execution
•  One time process: All vertex and pixel data are
evaluated and copied into the display list memory on the
server
•  For optimal performance, put matrix transforms, lighting
and material calculation inside display list, if possible
•  Fastest method to draw static data
Display List: Implementation
// create one display list
GLuint list = glGenLists(1);
void draw()
{
If NOT created
// compile the display list, store a triangle in it
glNewList(list, GL_COMPILE);
Red block
// GLBegin-GLEnd pair
// Or, your vertex array code here
else
glEndList();
Blue block
... // draw the display list
glCallList(index);
... // delete it if it is not used any more
glDeleteLists(index, 1);
}
Vertex Buffer Object (VBO)
•  Motivation
–  Combine the benefits of vertex array and display list, shredding
off their disadvantages
–  Vertex array is a client (CPU) side implementation
–  Display list works on server (GPU) side, but data cannot be
updated
–  VBO is a server side functionality which allows reading and
updating of data (vertices) by the client side
•  Definition (from OpenGL)
–  Mechanism for storing vertex data in "fast" memory (for example
video RAM), thereby allowing for significant increases in vertex
throughput between the application (CPU) and the GPU
Creating a VBO
• 
3 steps:
– 
– 
Generate a new buffer object with glGenBuffers()
•  creates buffer objects and returns the identifiers of the buffer
objects
•  Syntax: void glGenBuffers(GLsizei n, GLuint* ids)
Bind the buffer object with glBindBuffer()
•  hook the buffer object with the corresponding ID
• 
– 
Syntax: void glBindBuffer(GLenum target, GLuint id)
Copy vertex data to the buffer object with glBufferData()
•  copy the data into the buffer object
•  Syntax: void glBufferData(GLenum target, GLsizei size, const void* data,
GLenum usage)
– 
Specify Access pattern
• 
• 
STATIC, STREAM, DYNAMIC
DRAW, COPY, READ
Implementation
// ID of VBO
GLuint vboId;
// create vertex array
GLfloat* vertices = new GLfloat[vCount*3];
Read Model Here
... // generate a new VBO and get the associated ID
glGenBuffers(1, &vboId);
// bind VBO in order to use
glBindBuffer(GL_ARRAY_BUFFER, vboId);
// upload data to VBO
glBufferData(GL_ARRAY_BUFFER, datasize, vertices, GL_STATIC_DRAW);
// it is safe to delete after copying data to VBO
delete [ ] vertices;
... // delete VBO when program terminated
glDeleteBuffers(1, &vboId);
In bytes
Drawing a VBO
•  Rendering VBO is similar to vertex array
•  Only difference: the pointer to the vertex array is now an
offset to a currently bound buffer object
•  Example:
// Activate vertex array
glEnableClientState(GL_VERTEX_ARRAY);
// activate vertex coords array
glVertexPointer(3, GL_FLOAT, 0, 0); // last param is offset, not ptr
// draw 6 quads using offset of index array
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0);
// deactivate vertex array
glDisableClientState(GL_VERTEX_ARRAY);
Updating a VBO
•  Recall the advantage over display list: client can read
and modify the buffer object data
•  Option 1:
–  Copy new data into the bound VBO with
glBufferDataARB() or glBufferSubDataARB()
–  Need to have 2 copies of vertex data: one in your
application and the other in VBO
•  Option 2:
–  map the buffer object into client's memory, so that
client can update data with the pointer to the mapped
buffer
Details of option 2
•  map the buffer object into client's memory
–  Syntax: void* glMapBuffer(GLenum target, GLenum access)
•  synchronization issue
–  If GPU is still working with the buffer object,
glMapBuffer() will not return until GPU finishes
its job
•  After modifying the data of VBO, it must be
unmapped the buffer object from the client's
memory
–  Syntax: GLboolean glUnmapBuffer(GLenum target)
Implementation
// bind then map the VBO
glBindBuffer(GL_ARRAY_BUFFER, vboId);
float* ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// if the pointer is valid (mapping was successful), update VBO
if(ptr)
{
updateMyVBO(ptr, ...); // modify buffer data
glUnmapBuffer(GL_ARRAY_BUFFER); // unmap it after use
}
// you can draw the updated VBO ...
Download