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

Posted

技术标签:

【中文标题】没有 VAO 的每个着色器属性的 VBO 或不同的方法?【英文标题】:VBO per shader attribute without VAO, or different approach? 【发布时间】:2011-12-10 19:38:24 【问题描述】:

我在我的应用程序中使用了各种“嵌套”上下文(用于着色器和几何共享),因此我不能使用 VAO,因为它们不能跨上下文共享。

我的网格数据作为唯一顶点的“池”存储在一个 VBO 中,而在另一个 VBO 中我存储构成面的索引。我目前正在我的 CAD 应用程序中成功地使用它进行线框渲染,但我想添加一个平面阴影模式 - 为此我需要面部法线。

如果我需要顶点法线,我只需将数据附加到顶点位置数据,但在这里我不能这样做,因为顶点将具有不同的面法线,具体取决于它属于哪个面正在被渲染。理想情况下,我想创建另一个 VBO 对来保存我的面部法线和索引,但是如果没有 VAO,我无法将两个 VBO 绑定到同一个目标 - 即使它们用于不同的属性。

我很欣赏正常的路线是使用 VAO,它可以让您将多个 VBO 分配给同一个目标,但我不能使用它们,因为我的几何上下文是共享的,而 VAO 不是。这个问题有其他解决方案吗?

【问题讨论】:

【参考方案1】:

如果我需要顶点法线,我只需将数据附加到顶点位置数据,但在这里我不能这样做,因为顶点将具有不同的面法线,具体取决于它属于哪个面正在被渲染。理想情况下,我想创建另一个 VBO 对来保存我的面部法线和索引,但是如果没有 VAO,我无法将两个 VBO 绑定到同一个目标 - 即使它们用于不同的属性。

您的问题与 VAO 或缓冲区对象无关。 VAO 不允许您拥有多个索引列表。它们不允许您拥有“面部法线”。

vertex array objects 只不过是一个存储顶点属性绑定的容器。它们不能让你做任何没有它们你就不能做的事情;有一种简单的方法可以更改所有属性绑定。

您需要将顶点位置分解为不同的面。因此,您需要复制位置值,以便每个唯一位置/法线对都是正确唯一的。 VAO 无法绕过这个限制。

仅供参考:不共享 VAO 的原因是因为它们太简单而无法共享。您可以很容易地在两个不同的上下文中设置相同的 VAO。只需在您想要使用它的上下文中创建一个 VAO,然后按照您通常所做的设置它。它只是一个简单的状态对象;它实际上不包含任何内容。

【讨论】:

感谢您的快速回答。我怀疑可能是这种情况,但让我震惊的是 OpenGL Superbible 5ed "a record of the currently bound buffer is made in the current VAO and used for that attribute. That is, not only does glVertexAttribPointer tell OpenGL the offset into the buffer that a vertex attribute's can be found, but it also tells OpenGL which buffer contains the data. It is therefore possible to use multiple buffers - one for each attribute - simultaneously..." 中的一个部分。这让我很困惑,因为将缓冲区绑定到绑定目标会取消绑定旧缓冲区。 @cbamber85:确实如此。但是,您使用不同的缓冲区对象这一事实 意味着您使用不同的索引来访问它们。对多个属性使用相同的缓冲区与对多个属性使用多个缓冲区之间没有功能差异。唯一的区别是属性数据的来源。 啊,这很有道理,而且完全与我所看到的有关。

以上是关于没有 VAO 的每个着色器属性的 VBO 或不同的方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 GLSL 着色器中访问 VBO/VAO 数据

顶点着色器 VAO 是不是需要 VBO?

OpenGL - 如何理解 VAO 与 VBO 之间的关系

一个 VBO 可以绑定多个 VAO 吗?

glUseProgram 会改变 VAO 和/或 VBO 状态吗?

了解 VAO、VBO 和程序