0

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

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

然而,最近我开始使用 glDrawInstanced 使用硬件实例化,而实例属性在 VAO 中绑定在一起的事实使我的关注点分离变得更加困难。

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

当我有可用于正常渲染和实例化渲染的 VBO 时,这变得更加烦人。

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

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

4

1 回答 1

0

找到了一种方法!

我忘记了您实际上可以通过使用来检查 VAO 的状态glGetVertexAttrib*。这允许我的实例参数操作模块实际创建一个新的 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。

于 2016-04-17T10:06:08.840 回答