OpenGL下的VBO的图形绘制

为了避免反复向显卡传送相同的定点数据,绘制大量顶点数据时OpenGL下可以使用缓存对象(Buffer Object)来将数据上传到显卡。

准备数据

我们的显示数据为一正方体,如下所示

顶点数据结构为颜色(RGBA)法线(xyz)坐标(xyz)

顶点数据存储在vertices,定点的索引数据存储在indices,同时还需要缓存对象的句柄vertexBuffer和indexBuffer

struct CUSTOM_VERTEX{float r, g, b, a;float nx, ny, nz;float x, y, z;};CUSTOM_VERTEX vertices[] = {{ 1.0f, 0.0f, 0.0f, 1.0f, -0.577f, 0.577f, 0.577f, -1.0f, 1.0f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, -0.577f, -0.577f, 0.577f, -1.0f, -1.0f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, 0.577f, 0.577f, 0.577f, 1.0f, 1.0f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, 0.577f, -0.577f, 0.577f, 1.0f, -1.0f, 1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, 0.577f, 0.577f, -0.577f, 1.0f, 1.0f, -1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, 0.577f, -0.577f, -0.577f, 1.0f, -1.0f, -1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, -0.577f, 0.577f, -0.577f, -1.0f, 1.0f, -1.0f },{ 1.0f, 0.0f, 0.0f, 1.0f, -0.577f, -0.577f, -0.577f, -1.0f, -1.0f, -1.0f },};GLuint indices[] = {0, 2, 3, 1,2, 4, 5, 3,4, 6, 7, 5,6, 0, 1, 7,6, 4, 2, 0,1, 3, 5, 7,};int num_indices = sizeof(indices) / sizeof(indices[0]);int num_vertices = sizeof(vertices) / sizeof(vertices[0]);GLuint vertexBuffer;GLuint indexBuffer;初始化

glGenBuffers创建缓冲对象,句柄(创建对象的标示符)存储在vertexBuffer,本例中创建对象数量为1

glBindBuffer激活缓冲区,指定当前缓冲对象,从而使接下的操作都是对该对象进行的。GL_ARRAY_BUFFER表示顶点数据,GL_ELEMENT_ARRAY_BUFFER表示索引数据。

该函数有三个功能:

1.buffer(非0)为首次使用,创建新缓冲对象

2.buffer为已创建对象则激活该对象

3.buffer为0则停止使用该对象

glBufferData为缓存对象分配数据空间,,然后将数据从内存复制到缓冲对象,GL_STATIC_DRAW表示数据只复制一次,可多次用来绘图。

// 顶点缓存glGenBuffers(1, &vertexBuffer);glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);glBufferData(GL_ARRAY_BUFFER, num_vertices * sizeof(CUSTOM_VERTEX), vertices, GL_STATIC_DRAW);// 索引缓存glGenBuffers(1, &indexBuffer);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_indices * 4, indices, GL_STATIC_DRAW);// 解除绑定glBindBuffer(GL_ARRAY_BUFFER, 0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);使用缓存对象

// 激活缓存对象glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);// 指定数组格式glInterleavedArrays(GL_C4F_N3F_V3F, 0, NULL);// 开始绘制glDrawElements(GL_QUADS, num_indices, GL_UNSIGNED_INT, NULL);// 绘制完成,解除绑定// 转载请注明// 如有疑问欢迎留言glBindBuffer(GL_ARRAY_BUFFER, 0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

效果如下

缓存数据的更新

接下来时这更新顶点数据,可以使用glMapBuffer来获取(该方法适合大量更新的情况,部分更新时应使用glBufferSubData等其他函数)

本例中更新所有顶点的坐标让其随时间作正弦运动

t += 0.0001;GLfloat* data;data = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);if (data != (GLfloat*)NULL){for (int i = 0; i < num_vertices; i++){data[10 * i + 8] += 0.001*cos(t);}glUnmapBuffer(GL_ARRAY_BUFFER);}结果:

你在雨中行走,你从不打伞,你有自己的天空,它从不下雨。

OpenGL下的VBO的图形绘制

相关文章:

你感兴趣的文章:

标签云: