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);

    // 绘制完成,解除绑定
    //  转载请注明http://blog.csdn.net/boksic 
    //  如有疑问欢迎留言
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);



效果如下

OpenGL下的VBO的图形绘制_第1张图片

缓存数据的更新

接下来时这更新顶点数据,可以使用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的图形绘制_第2张图片










你可能感兴趣的:(CG技术)