关于VBO的一些东西
2014-07-12 10:41
323 查看
http://blog.sina.com.cn/s/blog_7cfb366d010158he.html
有时候你不得不承认,OPENGL的开发真的不如DIRECTX,特别对于入门的人来说,一个简单的概念可以让我嚼上几天不得骑姐。
VBO可以说是OPENGL中里程碑似的东西,通过VBO我们可以把需要渲染的图元的顶点信息,直接上传存储在GPU的显存中。
由于最早的OPENGL不支持实例化绘制,导致在绘制大量相似图元的时候,需要反复向GPU提交代码渲染,这点在OpenGL中的二次方图元和实例化绘制已经提到过了,会严重导致瓶颈效应,而VBO的诞生正好解决了这一问题,当然这特性需要OPENGL3.1以上或者扩展的支持。
说到VBO自然要说到VAO,但是实际上两者可以完全不相关,只是了解了VAO的机制,跟容易了解VBO而已。
说到底,VBO就是通过那几个函数,在GPU显存中创建一块BUFFER,用于存储和顶点以及其属性相关的信息。
了解了VAO并且了解了顶点数组和顶点索引以后,我们才可以进一步去了解VBO的使用。
所谓的顶点数组,就是如下的东西:
GLfloat vertices[] = {
-1.0, -1.0, -1.0 ,
-1.0, -1.0, 1.0 ,
-1.0, 1.0, -1.0 ,
-1.0, 1.0, 1.0 ,
1.0, -1.0, -1.0 ,
1.0, -1.0, 1.0 ,
1.0, 1.0, -1.0 ,
1.0, 1.0, 1.0 ,
};
上面是一个立方体的一共8个顶点,而顶点索引即如下
static GLshort frontIndices[] = {0, 1, 3, 2};
上面这个索引只包含了立方体的四个顶点即其中一个面而已
然后我们将这些个顶点数组和顶点索引上传至GPU的显存,如下
glGenBuffers(3,buffers);//创建3块buffer
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);//先将第一块buffer绑定到当前
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),vertices, GL_STATIC_DRAW);//将顶点数组放入这个buffer
glVertexPointer(3, GL_FLOAT, 0, 0);
//指定这个buffer的格式,3代表3个float值为一个顶点,第一个0代表跨度,这里数值是紧密排列的,最后一个是数组的入口地址*point,由于已经将buffer绑定到当前,所以填0
glEnableClientState(GL_VERTEX_ARRAY);//使用这个buffer,一定不要忘记
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);//这里开始是将第二块buffer绑定到当前,上传color数据,和顶点的做法一样,不多赘述了
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glColorPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);//将第三块buffer绑定到当前,用于上传存储顶点索引的数据,因此BUFFER类型变更为GL_ELEMENT_ARRAY_BUFFER
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(frontIndices),frontIndices,GL_STATIC_DRAW);//同样是对buffer进行填充
经过以上代码,某个图元的顶点位置以及颜色和索引信息就已经放入GPU了,接下来只要在display函数中,调用glDrawElements就可以绘制了
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));//由于索引定义的是4个点,因此第一个参数mode是四边形,第二个是索引的size,第三个是索引的数据类型。注意!glDrawElements只接受3种数据类型,当时我因为指定索引类型为GL_INT导致无法绘制被卡住了N长时间,坑人啊!最后一个是指针地址,由于当前绑定的buffer是buffer[2],因此填0即可。
最后别忘记了,VBO是需要glew库支持的,所以要记得在头文件中添加
需要补充的是,关于另外一个函数:glVertexAttribPointer
这个函数可以在很多人的代码中见到,普遍是用于GLSL。什么是GLSL,想想我就头大,简单图形的绘制完全用不到自己编写渲染器,自定义的渲染器这块内容我觉得和OPENGL本身一样水深的很,如果不是从事3D游戏开发,完全没必要去碰。言归正传,因为大量的这个函数的例子都出现在GLSL中,所以我也是费了很大的劲才搞清楚如何将它用在简单的OPENGL函数中。
简单的来说,它和之前我们用的glVertexPointer是同一个东西,只是如果用了glVertexAttribPointer,那么我们就不需要死板的只指定vertice为顶点位置,而是可以创建一个包含了所有顶点位置+顶点颜色+顶点法线+顶点xxx的数组,通过一次将其送入显存,然后调用glVertexAttribPointer索引其属性就可以实现。比方说我有个attrib[]数组,前3位为位置,后面依次为颜色,法线,这样子就有3个index,依次为0,1,2.在调用glVertexAttribPointer的时候,先
glEnableVertexAttribArray(0); 使能,在用代码glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0,0);就表示指定了buffer中的第一个索引为pos,然后用,颜色和法线如法炮制。
总结:其实VBO是很简单的东西,实现也是很简单的概念,但是大量的文章不是把关键的地方省略了,就是说的不够通俗易懂,所以还是比较坑人的
有时候你不得不承认,OPENGL的开发真的不如DIRECTX,特别对于入门的人来说,一个简单的概念可以让我嚼上几天不得骑姐。
VBO可以说是OPENGL中里程碑似的东西,通过VBO我们可以把需要渲染的图元的顶点信息,直接上传存储在GPU的显存中。
由于最早的OPENGL不支持实例化绘制,导致在绘制大量相似图元的时候,需要反复向GPU提交代码渲染,这点在OpenGL中的二次方图元和实例化绘制已经提到过了,会严重导致瓶颈效应,而VBO的诞生正好解决了这一问题,当然这特性需要OPENGL3.1以上或者扩展的支持。
说到VBO自然要说到VAO,但是实际上两者可以完全不相关,只是了解了VAO的机制,跟容易了解VBO而已。
说到底,VBO就是通过那几个函数,在GPU显存中创建一块BUFFER,用于存储和顶点以及其属性相关的信息。
了解了VAO并且了解了顶点数组和顶点索引以后,我们才可以进一步去了解VBO的使用。
所谓的顶点数组,就是如下的东西:
GLfloat vertices[] = {
-1.0, -1.0, -1.0 ,
-1.0, -1.0, 1.0 ,
-1.0, 1.0, -1.0 ,
-1.0, 1.0, 1.0 ,
1.0, -1.0, -1.0 ,
1.0, -1.0, 1.0 ,
1.0, 1.0, -1.0 ,
1.0, 1.0, 1.0 ,
};
上面是一个立方体的一共8个顶点,而顶点索引即如下
static GLshort frontIndices[] = {0, 1, 3, 2};
上面这个索引只包含了立方体的四个顶点即其中一个面而已
然后我们将这些个顶点数组和顶点索引上传至GPU的显存,如下
glGenBuffers(3,buffers);//创建3块buffer
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);//先将第一块buffer绑定到当前
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),vertices, GL_STATIC_DRAW);//将顶点数组放入这个buffer
glVertexPointer(3, GL_FLOAT, 0, 0);
//指定这个buffer的格式,3代表3个float值为一个顶点,第一个0代表跨度,这里数值是紧密排列的,最后一个是数组的入口地址*point,由于已经将buffer绑定到当前,所以填0
glEnableClientState(GL_VERTEX_ARRAY);//使用这个buffer,一定不要忘记
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);//这里开始是将第二块buffer绑定到当前,上传color数据,和顶点的做法一样,不多赘述了
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glColorPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);//将第三块buffer绑定到当前,用于上传存储顶点索引的数据,因此BUFFER类型变更为GL_ELEMENT_ARRAY_BUFFER
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(frontIndices),frontIndices,GL_STATIC_DRAW);//同样是对buffer进行填充
经过以上代码,某个图元的顶点位置以及颜色和索引信息就已经放入GPU了,接下来只要在display函数中,调用glDrawElements就可以绘制了
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));//由于索引定义的是4个点,因此第一个参数mode是四边形,第二个是索引的size,第三个是索引的数据类型。注意!glDrawElements只接受3种数据类型,当时我因为指定索引类型为GL_INT导致无法绘制被卡住了N长时间,坑人啊!最后一个是指针地址,由于当前绑定的buffer是buffer[2],因此填0即可。
最后别忘记了,VBO是需要glew库支持的,所以要记得在头文件中添加
需要补充的是,关于另外一个函数:glVertexAttribPointer
这个函数可以在很多人的代码中见到,普遍是用于GLSL。什么是GLSL,想想我就头大,简单图形的绘制完全用不到自己编写渲染器,自定义的渲染器这块内容我觉得和OPENGL本身一样水深的很,如果不是从事3D游戏开发,完全没必要去碰。言归正传,因为大量的这个函数的例子都出现在GLSL中,所以我也是费了很大的劲才搞清楚如何将它用在简单的OPENGL函数中。
简单的来说,它和之前我们用的glVertexPointer是同一个东西,只是如果用了glVertexAttribPointer,那么我们就不需要死板的只指定vertice为顶点位置,而是可以创建一个包含了所有顶点位置+顶点颜色+顶点法线+顶点xxx的数组,通过一次将其送入显存,然后调用glVertexAttribPointer索引其属性就可以实现。比方说我有个attrib[]数组,前3位为位置,后面依次为颜色,法线,这样子就有3个index,依次为0,1,2.在调用glVertexAttribPointer的时候,先
glEnableVertexAttribArray(0); 使能,在用代码glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0,0);就表示指定了buffer中的第一个索引为pos,然后用,颜色和法线如法炮制。
总结:其实VBO是很简单的东西,实现也是很简单的概念,但是大量的文章不是把关键的地方省略了,就是说的不够通俗易懂,所以还是比较坑人的
相关文章推荐
- 关于MD5的一些东西
- 关于FreeTextBox 1.63/2.0.7/3.0RC/3.0的一些东西
- 从网络上找到的一些关于软件工程的东西
- 虽然分了Delphi的目录,但是没有写一点关于Delphi的东西,这两天写了一些Delphi的东西,就顺便写到BLOG上吧
- 虽然分了Delphi的目录,但是没有写一点关于Delphi的东西,这两天写了一些Delphi的东西,就顺便写到BLOG上吧
- 一些关于RSS的东西
- 关于企业安全的一些东西
- 关于数据绑定的一些东西
- 新开张,写一些关于.net的东西!包括xml
- 关于FreeTextBox 1.63/2.0.7/3.0RC/3.0的一些东西
- 关于delphi的cxGrid的一些东西(有些粗略,以后慢慢补完)
- Google的秘密,对Google感兴趣,所以放上来一些关于Google的东西
- 关于JAVA-一些要记住的东西
- 最新想写一些关于Linux的东西
- 一些关于注册表有用的东西
- 5月11日,关于snmp的一些东西
- 关于OpenPOP/OpenSMTP/Mail.Net的一些东西……
- 虽然分了Delphi的目录,但是没有写一点关于Delphi的东西,这两天写了一些Delphi的东西,就顺便写到BLOG上吧
- 关于Rss的一些东西
- 关于机器人足球的一些东西