A Vertex Buffer Object (in short VBO) is an object(buffer) that holds vertex data. It's your job, as the programmer, to fill the VBO with this data (usually Vertex positions, texture coordinates and normals) and then send it to be handled by the GPU.
This is an example of VBO initialization:
glGenBuffers( 1, &vbo ); // Generate a VBO handler
glBindBuffer( GL_ARRAY_BUFFER, vbo ); // Bind the handler
glBufferData( GL_ARRAY_BUFFER, 3 * 6 * 4 * sizeof( float), cubeVertices, GL_STATIC_DRAW );
// Allocate and initialize storage space
We're saying that we want a VBO that will store 72 floats (3 coords xyz, 6 faces, 4 vertices per face).
cubeVertices is just an array of vertices (floats), and it has redundant vertice data (but don't mind that, it's just an example).
Later when you want to draw the cube you only have to bind the VBO again and draw it using a single function call. (Well, you still need a few more to bind buffers again).
By using VBOs you'll send your Vertex data only once during initialization, whereas using the deprecated functions
glBegin/glEnd/glVertex you would have to send Vertex data every frame.
Back to the
GL_STATIC_DRAW in my initialization example, this means that you won't be changing the buffer data later on. But you could also use
GL_DYNAMIC_DRAW so that you can change vertices later. There are other flags.
However, these flags are just a hint for the GPU to decide where and how to store them. A dynamic VBO is easier / faster to update than a static one, but you can also change data on a static VBO (though you should of course use the right flag for your purposes).
For more info check: https://www.opengl.org/sdk/docs/man3/xhtml/glBufferData.xml
And also: https://www.opengl.org/sdk/docs/man3/xhtml/glBufferSubData.xml
In OpenGL 3+, you'll also use Vertex Array Objects (or VAOs) that will store multiple VBOs. These can be setup to hold the data to be sent to your own shaders, so you can even make a VBO holding vertex temperature, vertex happiness, whatever you want.