关于VBO的一些东西

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是很简单的东西,实现也是很简单的概念,但是大量的文章不是把关键的地方省略了,就是说的不够通俗易懂,所以还是比较坑人的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值