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

Posted

技术标签:

【中文标题】在不同的 VBO 中存储不同的顶点属性【英文标题】:Storing different vertex attributes in different VBO's 【发布时间】:2011-08-28 20:15:35 【问题描述】:

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

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

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】:

属性位置 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) 重新分配它们)。任何一种方式都只有在流数据位于非流数据的另一个缓冲区对象中时才有效。

另一个可证明需要的例子是,如果内存是一个问题并且多个对象共享某些属性列表。也许对象具有不同的位置和法线数组,但具有相同的颜色和纹理坐标数组。或者类似的东西。

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

【讨论】:

非常感谢!我明白!很多其他的事情突然变得清晰了:))) 我的第二个问题呢?它通常被认为是一个好主意吗? 我现在看得更清楚了。非常感谢。因此,在简单的情况下,我们应该使用 Nicol 提到的第一种方法,如果需要,我们使用不同的 VBO。更清楚谢谢!

以上是关于在不同的 VBO 中存储不同的顶点属性的主要内容,如果未能解决你的问题,请参考以下文章

将两个不同的网格放在同一个顶点 VBO 中的 OpenGL 最佳实践

OpenGL Instancing VBO - 每个顶点,每个实例的属性

没有 VAO 的每个着色器属性的 VBO 或不同的方法?

首先在内部具有不同对象的 VBO 中定位

在 Vbo 中显示具有不同点大小的网格?

在两个不同的顶点数组对象中使用顶点缓冲区