VBO

1、什么是VBO?

顶点缓冲区对象VBO(Vertex Buffer Object), 将顶点数组存储在高性能的显存中,提升的绘制的速度。


2、why?

顶点数组可以减少函数调用、去除冗余的共享顶点;但是顶点数组存在自身的缺点,顶点数组是在客户端,这样数组中的数据每次被访问的时候都要传输到服务器端。

另外,显示列表是服务器端的函数,它没有数据传输耗费的问题。但是,每当显示列表被编译以后,其中的数据就不能在改变了。

鉴于以上两个问题,提出了VBO,即在显存中创建顶点缓冲区对象,可以与顶点数组一样被glVertexPointer(), glNormalPointer(), glTexCoordPointer()等函数访问。


3、优点

(1)与显示列表不同的是:VBO中的数据是可读、可更新的,具体方法是讲VBO映射到客户端的存储空间。

(2)VBO的另一个优点是:多个用户共享同一个缓冲区对象。因为VBO是在服务端,多个用户可以通过相应的标示符访问到同一个缓冲区。


4、operations

(1)创建VBO

//生成一个新的缓冲区对象
void glGenBuffersARB(GLsizei n, GLuint* ids)
//绑定缓冲区对象,也即选择(或者激活)一个缓冲区对象,因为可能创建了好多缓冲区对象,这是需要选择一个成为活动的
void glBindBufferARB(GLenum target, GLuint id)
//将顶点数据复制到缓冲区对象
void glBufferDataARB(GLenum target, GLsizei size, const void* data, GLenum usage)
//删除缓冲区对象
void glDeleteBuffersARB(GLsizei n, const GLuint* ids)


(2)绘制VBO

// bind VBOs for vertex array and index array
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId1);         // for vertex coordinates
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vboId2); // for indices

// do same as vertex array except pointer
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);

glDisableClientState(GL_VERTEX_ARRAY);            // deactivate vertex array

// bind with 0, so, switch back to normal pointer operation
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);


(3)更新VBO

void* glMapBufferARB(GLenum target, GLenum access)//将缓冲区对象映射到客户端存储区
GLboolean glUnmapBufferARB(GLenum target)



代码:

#include <iostream>
#include <gl/glew.h>
#include <gl/glut.h>
using namespace std;


// cube ///
//    v6----- v5
//   /|      /|
//  v1------v0|
//  | |     | |
//  | |v7---|-|v4
//  |/      |/
//  v2------v3

// vertex coords array for glDrawArrays() =====================================
// A cube has 6 sides and each side has 2 triangles, therefore, a cube consists
// of 36 vertices (6 sides * 2 tris * 3 vertices = 36 vertices). And, each
// vertex is 3 components (x,y,z) of floats, therefore, the size of vertex
// array is 108 floats (36 * 3 = 108).
GLfloat vertices[]  = { 
	1, 1, 1,  -1, 1, 1,  -1,-1, 1,      // v0-v1-v2 (front)
	-1,-1, 1,   1,-1, 1,   1, 1, 1,      // v2-v3-v0

	1, 1, 1,   1,-1, 1,   1,-1,-1,      // v0-v3-v4 (right)
	1,-1,-1,   1, 1,-1,   1, 1, 1,      // v4-v5-v0

	1, 1, 1,   1, 1,-1,  -1, 1,-1,      // v0-v5-v6 (top)
	-1, 1,-1,  -1, 1, 1,   1, 1, 1,      // v6-v1-v0

	-1, 1, 1,  -1, 1,-1,  -1,-1,-1,      // v1-v6-v7 (left)
	-1,-1,-1,  -1,-1, 1,  -1, 1, 1,      // v7-v2-v1

	-1,-1,-1,   1,-1,-1,   1,-1, 1,      // v7-v4-v3 (bottom)
	1,-1, 1,  -1,-1, 1,  -1,-1,-1,      // v3-v2-v7

	1,-1,-1,  -1,-1,-1,  -1, 1,-1,      // v4-v7-v6 (back)
	-1, 1,-1,   1, 1,-1,   1,-1,-1 };    // v6-v5-v4

// normal array
GLfloat normals[]   = { 
	0, 0, 1,   0, 0, 1,   0, 0, 1,      // v0-v1-v2 (front)
	0, 0, 1,   0, 0, 1,   0, 0, 1,      // v2-v3-v0

	1, 0, 0,   1, 0, 0,   1, 0, 0,      // v0-v3-v4 (right)
	1, 0, 0,   1, 0, 0,   1, 0, 0,      // v4-v5-v0

	0, 1, 0,   0, 1, 0,   0, 1, 0,      // v0-v5-v6 (top)
	0, 1, 0,   0, 1, 0,   0, 1, 0,      // v6-v1-v0

	-1, 0, 0,  -1, 0, 0,  -1, 0, 0,      // v1-v6-v7 (left)
	-1, 0, 0,  -1, 0, 0,  -1, 0, 0,      // v7-v2-v1

	0,-1, 0,   0,-1, 0,   0,-1, 0,      // v7-v4-v3 (bottom)
	0,-1, 0,   0,-1, 0,   0,-1, 0,      // v3-v2-v7

	0, 0,-1,   0, 0,-1,   0, 0,-1,      // v4-v7-v6 (back)
	0, 0,-1,   0, 0,-1,   0, 0,-1 };    // v6-v5-v4

// color array
GLfloat colors[]    = { 
	1, 1, 1,   1, 1, 0,   1, 0, 0,      // v0-v1-v2 (front)
	1, 0, 0,   1, 0, 1,   1, 1, 1,      // v2-v3-v0

	1, 1, 1,   1, 0, 1,   0, 0, 1,      // v0-v3-v4 (right)
	0, 0, 1,   0, 1, 1,   1, 1, 1,      // v4-v5-v0

	1, 1, 1,   0, 1, 1,   0, 1, 0,      // v0-v5-v6 (top)
	0, 1, 0,   1, 1, 0,   1, 1, 1,      // v6-v1-v0

	1, 1, 0,   0, 1, 0,   0, 0, 0,      // v1-v6-v7 (left)
	0, 0, 0,   1, 0, 0,   1, 1, 0,      // v7-v2-v1

	0, 0, 0,   0, 0, 1,   1, 0, 1,      // v7-v4-v3 (bottom)
	1, 0, 1,   1, 0, 0,   0, 0, 0,      // v3-v2-v7

	0, 0, 1,   0, 0, 0,   0, 1, 0,      // v4-v7-v6 (back)
	0, 1, 0,   0, 1, 1,   0, 0, 1 };    // v6-v5-v4


GLuint vboId = 0;

//camera
float cameraAngleX;
float cameraAngleY;
float cameraDistance = -5.0;

//mouse
bool mouseLeftDown;
bool mouseRightDown;
float LastXPos;
float LastYPos;


void initGL()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);


	glGenBuffers(1, &vboId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(normals)+sizeof(colors), 0, GL_STATIC_DRAW);
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
	glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(normals), normals);
	glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(normals), sizeof(colors), colors);
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);

	glPushMatrix();
	glLoadIdentity(); 

	glTranslatef(0, 0, cameraDistance);
	glRotatef(cameraAngleX, 1, 0, 0);   
	glRotatef(cameraAngleY, 0, 1, 0);   

	glBindBuffer(GL_ARRAY_BUFFER, vboId);

	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);

	glNormalPointer(GL_FLOAT, 0, (void*)sizeof(vertices));
	glColorPointer(3, GL_FLOAT, 0, (void*)(sizeof(vertices)+sizeof(normals)));
	glVertexPointer(3, GL_FLOAT, 0, 0);

	glDrawArrays(GL_TRIANGLES, 0, 36);

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glPopMatrix();

	glutSwapBuffers();
}

void reshape(int w, int h)
{
	glViewport(0, 0, w, h);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(60.0f, (GLfloat)w/(GLfloat)h, 0.01f, 100.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}


void mouse(int button, int state, int x, int y)
{

	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		mouseLeftDown = true;

		LastXPos = x;
		LastYPos = y;
	}

	if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
	{
		mouseRightDown = true;
	}
}


void mouseMotion(int x, int y)
{
	if (mouseLeftDown)
	{
		cameraAngleX += GLfloat(y - LastYPos)/GLfloat(20.0);
		cameraAngleY += GLfloat(x - LastXPos)/GLfloat(20.0);

		LastYPos = y;
		LastXPos = x;
	}
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(480, 640);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("VBO");

	glewInit();
	if(!glewIsSupported("GL_VERSION_2_0"))
	{
		fprintf(stderr, "ERROR: Support for necessary OpengGL extensions missing.");
	}

	initGL();

	glutDisplayFunc(display);
	glutIdleFunc(display);  
	glutReshapeFunc(reshape);
	glutMouseFunc(mouse);
	glutMotionFunc(mouseMotion);

	glutMainLoop();
	
	glDeleteBuffers(GL_ARRAY_BUFFER, &vboId);

	return 0;
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值