优化场景图

3

我有一个用C++编写的OpenGL标准场景图。

我的场景图有节点和形状。

节点是矩阵,应用它们的矩阵后,它们会绘制所有子节点。

void Node::draw(Affine3f amatrix) const
{
   amatrix = amatrix * matrix;
   for (Drawable* child : childern)
   {
      child->draw(amatrix);
   }
}

形状就是简单的打包好的VBO,它们会从绘制调用中获取矩阵,并将其设置为统一的模型视图矩阵,然后绘制VBO。

void Shape::draw(Affine3f mat) const
{
   renderer.setModelView(mat);
   myVertices.draw();
}

我喜欢这个设计,它非常简单灵活。但是,它非常低效,需要进行大量的CPU端矩阵乘法计算和绘制调用。

我的问题是:

如何优化此设计,同时消除不必要的矩阵乘法和绘制调用?

例如,仅在更改时计算矩阵而不是每次绘制重新计算,并将形状合并以便可以使用一次调用进行绘制。

一些更多的信息:

  • 形状是静态的(目前为止),包含的顶点将永远不会改变。
  • 存在静态几何体(位于根节点且未经操作)和动态几何体(操作节点的子元素)的混合。

如果您更清楚地定义您想要的内容,那么回答会更容易。从我的角度来看,除非您创建不必要的节点(这不是设计问题,而是您如何使用它的问题),否则您的设计中不包含不必要的矩阵乘法或不必要的绘制调用。所以再次问一下,您需要什么,以及哪些是不必要的乘法/绘制调用? - Grizzly
2个回答

4
一方面,为了传入矩阵,我会使用const &。您正在通过值传递,如果您有一些draw函数不需要对矩阵进行特殊处理,则会进行大量不必要的复制。
如果您想要避免在矩阵未更改时进行矩阵计算,则需要使用“dirty”标志来确定自上次使用以来矩阵的值是否发生了变化。RenderWare在其矩阵部分做了类似的事情。
否则,就像评论中所说的那样,在没有看到您的整体设计的情况下,您所拥有的东西本质上没有什么问题。

2
你是否在绘制树中的每个元素,即使它不可见?如果是这样,你应该尝试使用八叉树来过滤掉不可见的节点。
你也可以尝试在着色器中通过传递变量来执行大部分矩阵计算。我还看到你的矩阵是仿射的,但也许你仍然在实现中进行了昂贵的反演计算。如果是这种情况,你可以查看我的教程以了解如何使其廉价化。

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