重用VBO进行硬件实例化

时间:2016-04-16 18:39:35

标签: opengl opengl-4 geometry-instancing

通常我会尝试将网格特定信息(VBO / VAO)与特定于实例的信息(变换,制服等)分开。

通过这种方式,操作实例信息的部分代码不需要了解VBO / VAO的任何信息,反之亦然。

然而,最近我开始使用glDrawInstanced进行硬件实例化,并且实例属性在VAO中绑定在一起这一事实使我更加关注我的问题。

原因是通常VBO / VAO是从我的.OBJ加载器构建的(它具有构建它所需的所有信息),然后代码的其他部分只担心着色器制服。现在,代码的这些部分需要了解VAO的结构,以便附加有关其实例属性的信息。

当我拥有可以重复用于普通和实例渲染的VBO时,这会变得更加烦人。

是否有建议的方法可以在设置网格属性和实例属性之间保持关注点分离?

我想过有两个VAO,一个用于正常渲染,另一个用于实例渲染,我将添加我需要的额外实例属性,但我发现无法复制或检查原始VAO数据,因此我的组件似乎需要了解VBO / VAO的实际结构,而不仅仅是实例参数。

1 个答案:

答案 0 :(得分:0)

找到了办法!

我忘记了您可以使用glGetVertexAttrib*实际检查VAO的状态。这允许我的实例参数操作模块实际创建一个新的VAO用于实例化并从原始网格VAO重建其基本结构,然后为实例化参数添加其他属性。

这样它们可以保持独立于网格的特定顶点结构,只需要担心实例化数据的结构。

检查是这样的:

std::vector<VertexAttrib> attribs;
for (int i = 0; ; i++)
{
  int enabled;
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
  if (enabled == 0) break;

  VertexAttrib attrib;
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib.size);
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib.stride);
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib.type);
  glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &attrib.normalized);
  attribs.push_back(attrib);
}

VertexAttrib是我自己的结构,用于存储内省的顶点属性状态。

一旦我获得了内省状态列表,我就创建并绑定我的新VAO并将其状态设置为与原始VAO相同。然后我继续为硬件实例添加额外的属性。这也有一个好处,我可以将这个新的VAO绑定到原始VBO并重用完全相同的网格数据。

然后一切都按照正常的实例管道进行。如果我需要在没有实例化的情况下绘制模型,我也可以绑定原始的VAO。