« 学一学,VBO不要犹豫了,用sstream吧 »

索引顶点的VBO与多重纹理下的VBO

VBO的核心是顶点数组的使用,因此顶点索引数组和多重顶点纹理坐标数组的设置才是本文的核心。当然还有的是,它们在VBO下是什么样子的。——ZwqXin.xom

紧接上篇:[学一学,VBO]

本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
      原文地址:http://www.zwqxin.com/archives/opengl/indexed-vbo-and-multitex-vbo.html

1.索引顶点的VBO

在VA(顶点数组)下,索引数据被放入一个名为索引数组的“容器”里,在绘制的时候跟其他顶点属性一样,要先用glEnableClientState(GL_INDEX_ARRAY),再用glIndexPointer指定该容器……这一切在VBO中都是不需要的。因为它与glDrawElements函数必定一起出现,所以VBO通过同一标志位GL_ELEMENT_ARRAY_BUFFER把它们的关系“确定”下来。只需要创建一个储存索引数据索引的VBO,渲染时绑定,调用glDrawElements时,第二参数是索引数据的大小,足矣。

  1. //初始化部分
  2.     glGenBuffers(1, &mIndexBufferObject);
  3.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferObject);
  4.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, IndexDataSize, IndexData, GL_STREAM_DRAW);
  5.  
  6. //渲染部分
  7.     glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferObject);
  8.     glEnableClientState(GL_VERTEX_ARRAY);
  9.     glVertexPointer(3, GL_FLOAT, 0, 0);
  10.  
  11.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferObject);
  12.  
  13.     glDrawElements(GL_QUADS, IndexSize, GL_UNSIGNED_INT, 0);
  14.  
  15.     glDisableClientState(GL_VERTEX_ARRAY);
  16.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

现在我要用VBO技术画一个网格。网格看起来是这样的:

www.zwqxin.com   VBO索引

其中1,2,3,4......是放入顶点数组(GL_VERTEX_ARRAY)里的点的顺序。因为这种存放方式(行扫描)最方便。但是绘制的时候不能按这种顺序绘制(即不能直接用glDrawArrays),应该是一小块一小快矩形来画:1-8-9-2,2-9-10-3,3-10-11-4......6-13-14-7,8-15-16-9........而这个就是所谓的顶点索引,它决定了调用顶点的先后次序,取出顶点数据中相应索引的数据作画。结合顶点位置数据VBO的glVertexPointer对数据的解析(3个FLOAT数据为一组决定一个顶点),以及glDrawElements对数据的解析(4个顶点一组成为QUAD),整个流程就是这样了。注意索引的数据格式是GL_UNSIGNED_INT/GL_UNSIGNED_SHORT,我没尝试过其他(听说是不行的)。

  1.  
  2. //初始化时,设定索引数据的过程
  3.     int IndexSize = (ZSCALE - 1) * (XSCALE - 1) * 4;
  4.     GLsizeiptr IndexDataSize = IndexSize * sizeof(GLuint);
  5.  
  6.     GLuint *IndexData = new GLuint[IndexSize];
  7.     i = 0;
  8.     for(z = 0; z < ZSCALE - 1; ++z) 
  9.       for(x = 0; x < XSCALE - 1; ++x)
  10.       {
  11.         index = x + z * XSCALE;
  12.         IndexData[i]   = index;
  13.         IndexData[i+1] = index + XSCALE;
  14.         IndexData[i+2] = index + 1 + XSCALE;
  15.         IndexData[i+3] = index + 1;
  16.  
  17.         i += 4;
  18.       }

VBO WWW.ZWQXIN.COM

2.多重纹理下的VBO

其实多重纹理的VBO不是很复杂,但是网上介绍VBO的文章很少涉及这方面,加上网上外国论坛的帖子里的解释内容又不清不楚,所以我还是靠自己不断尝试,不断调整语句的顺序——花了差不多一晚才弄清楚的。

初始化的时候其实与其他顶点属性是一样的,也没必要设多个VBO,一个就可以了:

  1. //
  2.    GLsizeiptr TexCoordDataSize = XSCALE * ZSCALE * sizeof(TexCoord);
  3.     glGenBuffers(1, &mTexCoordBufferObject);
  4.     glBindBuffer(GL_ARRAY_BUFFER, mTexCoordBufferObject);
  5.     glBufferData(GL_ARRAY_BUFFER, TexCoordDataSize, Watertex, GL_STREAM_DRAW);

渲染的时候,注意,以前的glActiveTexture不要扔掉!不要。glEnable(GL_TEXTURE_2D)也不要扔掉。我们弄的是纹理坐标而不是纹理。前者可以作为客户端状态后者不能[学一学,VBO] ,我们还是需要通知服务端启用纹理与否的。

  1. //
  2.   glActiveTexture(GL_TEXTURE0);
  3.     glEnable(GL_TEXTURE_2D);
  4.     glBindTexture(GL_TEXTURE_2D, Tex0);
  5.  
  6.  
  7.     glActiveTexture(GL_TEXTURE1);
  8.     glEnable(GL_TEXTURE_2D);
  9.     glBindTexture(GL_TEXTURE_2D, Tex1);
  10.  
  11.     glActiveTexture(GL_TEXTURE2);
  12.     glEnable(GL_TEXTURE_2D);
  13.     glBindTexture(GL_TEXTURE_2D, Tex2);
  14.  
  15. ..........
  16.  
  17.     glBindBuffer(GL_ARRAY_BUFFER, mTexCoordBufferObject);
  18.     glClientActiveTexture(GL_TEXTURE0);
  19.     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  20.     glTexCoordPointer(2, GL_FLOAT, 0, 0);
  21.  
  22.     glClientActiveTexture(GL_TEXTURE1);
  23.     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  24.     glTexCoordPointer(2, GL_FLOAT, 0, 0);
  25.  
  26.     glClientActiveTexture(GL_TEXTURE2);
  27.     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  28.     glTexCoordPointer(2, GL_FLOAT, 0, 0);
  29.  
  30.     ..............
  31.                     glDarwArrays / glDrawElements
  32.     ..............
  33.  
  34.     glClientActiveTexture(GL_TEXTURE0);
  35.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  36.     glClientActiveTexture(GL_TEXTURE1);
  37.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  38.     glClientActiveTexture(GL_TEXTURE2);
  39.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  40.  
  41.     glActiveTexture(GL_TEXTURE2);
  42.     glDisable(GL_TEXTURE_2D);
  43.     glActiveTexture(GL_TEXTURE1);
  44.     glDisable(GL_TEXTURE_2D);
  45.     glActiveTexture(GL_TEXTURE0);
  46.     glDisable(GL_TEXTURE_2D);

多重纹理坐标VBO的整个过程跟多重纹理的设置过程是差不多的。但它体现起来是更改客户端状态(虽然VBO不经过客户端作二次传送,但是因为是继承VA.....)。glClientActiveTexture和glActiveTexture类似,都是用来指定当前使用的纹理句柄的,之后是glEnableClientState进行激活动作,再用glTexCoordPointer指定VBO内的数据的格式。再让阁下注意,这都是针对纹理坐标VBO的。

3.Interleaved arrays & Serialized arrays

参考此文OpenGL Vertex Buffer Objects -  PRACTICE

Interleaved arrays可以进一步减少函数调用的次数,主要是减少VBO的数量……但总觉得这样有点矫枉过正了。

  1. //
  2. #pragma pack(push, 1)
  3. struct SVertex
  4. {
  5.     GLubyte r;
  6.     GLubyte g;
  7.     GLubyte b;
  8.     GLfloat x;
  9.     GLfloat y;
  10. };
  11. #pragma pack(pop)

譬如这样把两类数据装一起,就只要一个VBO来存储数据就可了。但渲染时glXXXPointer还得设置stride间距值(如果用glInterleavedArrays反而更不好,参考文说的)……。另外pragma pack可以切除编译器4字节对宽的优化,不过不给优化不就"减速"了嘛……

参考文也这么认为。所以倡议同样减少函数调用次数,减少VBO个数的Serialized arrays。其实就是把两种或多种顶点属性的数据前后拼一起放入一个VBO里而已。然后更新的时候用glBufferSubData[学一学,VBO] 只更新数据里头需要被更新的那一段。glBufferSubData第二个参数是OFFSET了。确实这样比Interleaved arrays的做法好不少。

本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
      原文地址:http://www.zwqxin.com/archives/opengl/indexed-vbo-and-multitex-vbo.html

  • quote 1.yanite
  • 郁闷了, 画不出来。 不用索引数组可以画出来,用了就画不出来了。
    求解。
    zwqxin 于 2012-4-16 21:51:02 回复
    只能说你应该是某些地方疏忽了,譬如状态设错了。要给我重新排一次多重纹理VBO的话估计也得晕,所以说还是Shader好啊 - -
    ydw 于 2013-7-15 21:14:06 回复
    GL_INDEX_ARRAY与glIndexPointer是颜色索引模式下的颜色索引,不是绘图时顶点的索引,不要弄混了
  • 2012-4-15 23:03:37 回复该留言
  • quote 2.I飞影
  • “索引数据被放入一个名为索引数组的“容器”里,在绘制的时候跟其他顶点属性一样,要先用glEnableClientState(GL_INDEX_ARRAY),再用glIndexPointer指定该容器……这一切在VBO中都是不需要的。因为它与glDrawElements函数必定一起出现”,这也就是说只能存在一个索引。要是顶点、法线、纹理坐标的索引不一样,不就不能使用FBO了?
    zwqxin 于 2012-8-31 19:56:17 回复
    重新组织数据,让它们统一索引。
  • 2012-8-31 14:32:15 回复该留言
  • quote 3.zhwGIS
  • 请问为什么我用glDrawElements(GL_QUADS, IndexSize, GL_UNSIGNED_INT, 0)绘制就出错,如果IndexSize/4的话,可以绘制出四分之一,不知道什么原因,请大神指点一二。
  • 2013-5-30 10:43:10 回复该留言

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

IE下本页面显示有问题?

→点击地址栏右侧【兼容视图】←

日历

Search

网站分类

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Walle Build 100427

Copyright 2008-2013 ZwqXin. All Rights Reserved. Theme edited from ipati.