您的位置:首页 > 运维架构

OpenGL学习笔记(八)

2012-12-10 14:41 459 查看
顶点数组对象(vao)

随着程序逐渐增大并且使用更多的模型,读者可能发现要在每个帧的多组顶点数组之间切换。根据你为每个顶点使用多少个顶点属性,像对glVetexPointer()这样的函数的调用次数可能变得很大。顶点数组对象捆绑了调用的集合,以设置顶点数组的状态。在初始化之后,可以通过单次调用在不同的顶点数组集合之间快速修改。

创建顶点数组对象标识:

void glGenVertexArrays(GLsizei n,GLuint *arrays);

返回n个当前未使用的名字,记录在数组arrays。

绑定顶点数组对象:

GLvoid glBindVertexArray(GLuint array);

该函数做3件事情:

1.
当使用的值array不是零并且是从glGenVertexArrays()返回的值时,创建一个新的顶点数组对象并且分配该名字。

2.
当绑定的之前创建的一个顶点数组对象时,该顶点数组对象变成活动的,这影响到存储在该对象中的顶点数组状态

3.
当绑定到一个为零的array值时,OpenGL停止使用顶点数组对象并且返回顶点数组的默认状态

注意:如果array不是之前从glGenVertexArrays()返回的值;如果它是glDeleteVertexArrays()已经释放的值;如果调用了任何一个gl*Pointer()函数来指定一个顶点数组,而在绑定一个非零顶点数组对象的时候,它没有和一个缓冲区对象关联起来,将会产生GL_INVALID_OPERATION错误。

删除顶点数组对象:

void glDeleteVertexArrays(GLsizei n,GLuint *arrays);

删除arrays中指定的n个顶点数组对象,使这些名字随后可以作为顶点数组重用。

确定一个特定的值是否可以表示一个已分配的顶点数组对象,可调用:

GLboolean glIsVertexArray(GLuint array);

如果array是之前glGenVertexArrays()产生的一个顶点数组对象的标识,且没有删除则返回GL_TRUE;如果array是0或者一个非顶点数组对象标识的非零值则返回GL_FALSE。

示例:展示使用顶点数组对象在两组顶点数组之间进行切换

#define BUFFER_OFFSET(offset) ((GLvoid *)NULL + offset)

#define NumberOf(array) (sizeof(array)/sizeof(array[0]))

typedef struct{

GLfloat x,y,z;

} vec3;

Typedef struct{

vec3 xlate;

GLfloat angle; //旋转角度

vec3 axis; //旋转轴

} XForm;

GLuint VAO[2]; //记录数组对象标识

GLenum PrimType[2]; //

GLsizei NumElements[2]; //记录索引长度

XForm xform[2]={

{{-2.0,0.0,0.0},0.0,{0.0,1.0,0.0}},

{{0.0,0.0,2.0},0.0,{1.0,0.0,0.0}}

};

GLfloat Angle = 0.0;

void ini{

glGenVertexArrays(2,VAO); //创建顶点数组对象标识

GLuint buffers[3]; //[0]记录顶点标识,[1]记录颜色标识,[2]记录索引标识

for(int n=0;n<2;n++){

GLfloat *verts;//顶点数组

GLfloat *colors;//颜色数组

GLubyte *indices;//索引数组



//初始化顶点、颜色、索引数组



glBindVertexArray(VAO
); //绑定顶点数组对象

glGenBuffers(3,buffers); //创建缓冲区对象标识

glBindBuffer(GL_ARRAY_BUFFER,buffers[0]); //绑定顶点缓冲区对象

glBufferData(GL_ARRAY_BUFFER,sizeof(verts),verts,GL_STATIC_DRAW);//填充顶点数据

glVertexPointer(3,GL_FLOAT,0,BUFFER_OFFSET(0));

glEnableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER,buffers[1]); //绑定颜色缓冲区对象

glBufferData(GL_ARRAY_BUFFER,sizeof(colors),colors,GL_STATIC_DRAW);//填充颜色数据

glColorPointer(3,GL_FLOAT,0,BUFFER_OFFSET(0));

glEnableClientState(GL_COLOR_ARRAY);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[2]); //绑定索引缓冲区对象

glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices), indices,GL_STATIC_DRAW);//填充索引数据

PrimType
= GL_QUADS; //这里使用该值只是作为示例

NumElements
= NumberOf(indices);

}

glEnable(GL_DEPTH_TEST); //启用深度测试

}

void display(){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕

glPushMatrix(); //将当前矩阵状态入栈,进行保存

glRotatef(Angle,0.0,1.0,0.0); //旋转

for(int i=0;i<2;i++){

glPushMatrix(); //矩阵入栈

//下面进行一些矩阵变换操作

glTranslatef(xform[i].xlate.x, xform[i].xlate.y, xform[i].xlate.z);

glRotatef(xform[i].angle, xform[i].axis.x, xform[i].axis.y, xform[i].axis.z);

//

glBindVertexArray(VAO[i]); //激活指定顶点数组对象

glDrawElements(PrimType[i], NumElements[i]); //绘制

glPopMatrix(); //矩阵出栈

}

glPopMatrix(); //矩阵出栈,恢复原先状态



}

附:对VBO和VAO的一些看法

VBO是Vertex Buffer Object(顶点缓冲区对象),VAO是Vertex
Array Object(顶点数组对象)。

VBO其实就是显卡中的显存,为了提高渲染速度,可以将要绘制的顶点数据缓存在显存中,这样就不需要将要绘制的顶点数据重复从CPU发送到GPU,浪费带宽资源。

而VAO则是一个容器,可以包含多个VBO,它类似于以前的call list,由于它进一步将VBO容于其中,所以绘制效率将在VBO的基础上更进一步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: