OpenGL处理多个对象

6
我在理解如何处理/渲染多个OpenGL对象方面有一些困难。我在谷歌和OpenGL红宝书上找到了答案,但是内容并没有完全涉及到我的问题,所以我需要确认自己的理解是否正确。
我的第一个想法是使用X、Y和Z轴的平移和旋转变量来处理位置数据。为该类存储一个单一网格的静态VBO,然后对于我想要呈现的每个实例,需要用一个for-next循环来:
  • 加载身份
  • 将其转换到特定对象的位置/旋转
  • 使用drawarrays在该位置呈现网格
  • 循环到下一个对象,重复以上步骤直到所有对象都被呈现
每帧更新时,这样处理变换会显著影响性能吗?
另外一个方法是将每个顶点的所有位置数据粘在一个单独的VBO中,然后使用单个调用来呈现它。在这种方法中,我假设要“创建”一个对象,需要通过一个函数处理每个顶点的位置数据(通过静态数组),并将该特定对象的位置数据添加到顶点中,然后将其存储在VBO中?如果是这样,那如何处理旋转?
第三个想法是在每个对象的实例中存储一个4x4矩阵,该矩阵将保持平移/旋转信息。然后当我准备呈现时,只需加载该对象的矩阵,从单个VBO绘制网格,然后加载下一个对象的矩阵,从同一个VBO绘制,依此类推。
最后,我看到有些人建议为每个单独的对象设置一个VBO,并为每个实例调用drawarray。这种方式对我来说非常低效,让我想知道如果您为每个网格调用VBO的话,那么VBO的存在还有什么意义。似乎立即模式(我知道已被淘汰)会更快,因为您没有创建和绑定每个单独对象的VBO的开销。
这些处理/呈现多个对象的方法是否有效?如果是,每种方法的优缺点是什么?
最有意义的方法是为每个网格设置单个VBO,然后通过更新将其转换,或者每次更新都加载每个对象的矩阵并进行呈现。我对OpenGL和图形渲染相当新,因此我正在尝试充分了解渲染多个对象所需的信息的最佳方式。
1个回答

3
  • 转换到特定对象的位置/旋转

这就是简单地将一个4x4的矩阵加载到一个uniform变量中。

每帧更新时处理这些变换会显著影响性能吗?

这个变换将在你的顶点着色器中执行,通过将前面提到的矩阵乘以顶点坐标,并且并行地应用于许多顶点。

有人提到的另一种方法是将每个顶点的位置数据都粘贴到单个VBO中,然后使用单个调用进行渲染。 在这种方法中,我假设要“创建”一个对象,需要通过函数处理每个顶点的位置数据(通过静态数组),并将该特定对象的位置数据添加到顶点中,然后将其存储在VBO中。如果是这样,如何处理旋转呢?

这似乎不是一个很好的主意,因为您将不得不在每一帧上传数据(或者至少在对象位置/方向更改时)。

第三种方法似乎与第一种方法相同,只是使用了OGL3+术语,而第一种方法则使用了OGL 2.x术语:)

最后,我看到有些人建议为每个单独的对象拥有一个VBO,并为每个实例调用drawarray。

也许您误解了,他们指的是VAO,而不是VBO吗?使用VAO,您上传顶点属性(在VBO中),绑定VAO,将每个VBO绑定到适当的属性位置,并仅在开始时执行此操作一次。每帧只需执行:

// Bind the VAO
glBindVertexArray(vao)

// Draw the object
glDrawArrays/glDrawArraysInstanced/etc.

// CLear VAO binding
glBindVertexArray(0)

请注意,您仍然可以在同一VBO中拥有许多不同对象的顶点属性,记住glDrawArrays和其他函数有一个参数,该参数决定从数组中的哪个位置开始绘制。

1
如果一组对象的位置是静态的,即不会动态改变,则将它们全部放入单个VBO中,并使用公共变换绘制它们,通过单个glDrawElements调用绘制所有对象比迭代每个对象逐个绘制更高效。但仅适用于静态几何和位置。 - datenwolf
1
这绝对是VBO而不是VAO。那么我的问题是:我是否应该将每个对象的矩阵存储到VBO中,然后通过绑定的VAO传递给着色器? - David Torrey
1
如果您正在进行实例绘制,是的。例如,您可以使用“glVertexAttribDivisor”将模型视图矩阵设置为实例属性。或者,您可以将矩阵设置为统一的数组,并使用“gl_InstanceID”索引该数组。至于非实例化绘制,我不知道在着色器中如何合理地确定要使用哪个矩阵。 - chill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接