在不同的VBO中存储不同的顶点属性

时间:2011-08-28 20:15:35

标签: c++ opengl vbo

是否可以在不同的顶点缓冲区中存储不同的顶点属性?

到目前为止我见过的所有例子都是这样的

float data[] = 
{
//position
   v1x, v1y, v1z,
   v2x, v2y, v2z,
   ...
   vnx, vny, vnz,

//color
   c1r, c1g, c1b,
   c2r, c2g, c2b,
   ...
   cnr, cng, cnb,   
};
GLuint buffname;
glGenBuffers(1, &buffname);
glBindBuffer(GL_ARRAY_BUFFER, buffname);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

绘图完成如下:

glBindBuffer(GL_ARRAY_BUFFER, buffname);
glEnableVertexAttrib(position_location);
glEnableVertexAttrib(color_location);
glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(color_location, 3, GL_FLOAT, GL_FALSE, 0, (void*)(3*n));

glDrawArrays(GL_TRIANGLES, 0, n/3);

glDisableVertexAttrib(position_location);
glDisableVertexAttrib(color_location);
glBindBuffer(GL_ARRAY_BUFFER, 0);

是否有可能将位置数据和颜色数据存储在不同的VBO中?问题是我不明白这会如何解决,因为你不能同时绑定两个缓冲区,对吗?

如果有一个简单但效率低下的解决方案,我宁愿选择更复杂但更有效的解决方案,因为我处于初级学习状态,而且我不想太复杂化。

另外,如果我问的是可能的,这是不是一个好主意?

澄清: 我确实知道如何在不同的VBO中存储不同的属性。我不明白我以后会如何画它们。

1 个答案:

答案 0 :(得分:10)

属性位置X与提供该属性的缓冲区对象之间的关联是使用glVertexAttribPointer命令进行的。它的工作方式很简单,但不直观。

glVertexAttribPointer被调用(这是许多人无法获得的部分)时,当前绑定到GL_ARRAY_BUFFER的任何缓冲区对象都与属性X,其中X是glVertexAttribPointer的第一个参数。

因此,如果您想拥有一个来自一个缓冲区的属性和来自另一个缓冲区的属性,那么您可以这样做:

glEnableVertexAttrib(position_location);
glEnableVertexAttrib(color_location);
glBindBuffer(GL_ARRAY_BUFFER, buffPosition);
glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, buffColor);
glVertexAttribPointer(color_location, 3, GL_FLOAT, GL_FALSE, 0, 0);

至于你是否应该将属性分成不同的缓冲区...我会说你应该只在你有一个可证明的需要时才这样做。

例如,假设你正在做一个动态高度图,也许是为了某种水效果。每个元素的Z位置都会发生变化,但这也意味着法线会发生变化。但是,XY位置和纹理坐标不会改变。

高效的流式传输通常需要双缓冲缓冲区对象或使它们无效(使用glBufferData(NULL)或glMapBufferRange(GL_INVALIDATE_BIT)重新分配它们)。这两种方法只有在流数据位于非流数据的另一个缓冲区对象中时才有效。

可证明需求的另一个例子是内存是一个问题,并且几个对象共享某些属性列表。对象可能具有不同的位置和正常数组,但颜色和纹理坐标数组相同。或类似的东西。

但除此之外,最好将对象的所有内容放入一个缓冲区。即使你没有交错数组。