首页 > 解决方案 > 如何将 VBO 中的单个值传递给每个顶点?

问题描述

我有一个 VBO,其中包含一个接一个存储的多个 3d 模型,目的是通过多次调用 glDrawElements 等函数有条件地绘制模型。每个模型都意味着有一个固定的位置。在每次调用 glDrawElements 之前,我可以将模型的位置作为制服传递,但是因为有很多模型这样做是非常昂贵的。

我想将每个模型(而不是每个顶点)的每个模型位置存储在 VBO 内存中一次,并在绘制该模型时从着色器中的每个顶点访问它。

我希望有一个顶点属性指针,其偏移量指向模型位置,步幅为 0,这样它就不会增加每个顶点的内存,但不幸的是,步幅为 0 会使指针向前移动,就好像它很紧打包。

有什么办法可以完成我想要的吗?另外,我很好奇为什么 OpenGL 不允许步长为 0。它会很方便。

标签: openglopengl-3

解决方案


可以将步幅设置为 0。您只需使用顶点属性绑定 API。设置的步幅可以为 0,并且具有预期的含义(因为无法从可用参数glBindVertexBuffer中确定紧凑的步幅应该是什么)。

但是,如果您这样做是为了提高性能,那么这并不是特别有用。要在 VBO 中切换到不同的值,您必须发出glBindVertexBuffer调用,这将与glProgramUniform调用一样昂贵。事实上,根据 NVIDIA 的AZDO 演示文稿,更改制服比顶点缓冲区绑定更便宜。

如果您想节省统一更新的成本,那么您将不得不使用其他东西。您最好的选择是将您的每个网格“制服”放入 SSBO(或 UBO,如果您没有那么多模型),然后一次绘制所有网格(因此它们必须来自相同的顶点缓冲区具有相同的顶点格式)使用单个glMultiDraw*命令。然后您必须使用 GL 4.6/ARB_shader_draw_parameters 功能从您的着色器访问gl_DrawID,以选择从 SSBO 数组中提取哪个“统一”值。

这允许您使用单个绘制命令绘制所有这些对象。


推荐阅读