我是OpenGL ES的新手,我正在编写一个iPad应用程序,它需要我加载一个Wavefront Obj文件,在OpenGL中绘制它们。我的问题是关于渲染Obj文件组的最有效方法。
关于我所掌握的一些背景知识。Obj模型的所有解析/加载工作都在进行中(我使用GLM加载文件),因此繁琐的工作就不复存在了。对于基础项目,我在XCode中扩展了OpenGL ES游戏模板,并删除了对着色器的所有调用。我使用GLKit的BaseEffect为我的着色器,并加载我所有的顶点数据使用VAO和VBO。对于一个有16个组的模型,在初始化时,我将每个组分成一个VAO,每个VAO有一个用于顶点数据和法线(交错)的VBO,以及另一个用于纹理坐标的VBO。每组都有一种材质(有时还有一种纹理,但为了解决这个问题,只假定材质)。
在我的渲染例程(下面的伪代码)中,我循环遍历我为每个组创建的所有VAO,将组的材质应用到BaseEffect,然后使用DrawArrays绘制它(而不是使用DrawElements,因为我已经设置了VBO,所以数据已经按索引顺序排列,尽管它可能没有在图形内存中那么有效)。这是可行的,我可以用不同的材质绘制每个模型,但随着组数的增加,我的帧率会下降,因为我必须花费更多的时间在渲染函数中循环遍历每个组。对于较低的模型数,这是很好的,但随着我向应用程序添加更多的模型,帧速率远低于30fps,这是我的基准。
for (groups in model)
{
Bind VAO for this group
Apply Material or Texture (if one exists) for this group using GLKBaseEffect
Call PrepareToDraw for GLKBaseEffect
DrawArrays passing it the vertex count for this group
glBindVertexArray(0)
}
显而易见的答案是简化模型,以便有更少的组,但我很好奇渲染例程是否有任何改进,可以让我做同样的事情,但减少绘制调用。我希望仍然有一个详细的obj文件,但也有最有效的渲染我可以。
这是绘制obj文件的最好方法吗?我必须为文件中的每个组使用多个材质/纹理,还是有一种方法可以做到这一点,而不是循环每个组并单独绘制它们?我希望每个obj模型只有一次对DrawArray/DrawElements的调用,但我不知道如何在对对象应用多种材质/纹理的情况下做到这一点。我一直在看着这段代码,想着“一定有更好的方法”,但我不确定那是什么。如果我遗漏了显而易见的一块拼图,或者如果你有任何建议可以优化这一点,我将永远感激。
发布于 2012-06-26 22:43:57
我认为你的想法是正确的。实际上,一次只能有一组纹理或一个材质球处于活动状态,因此必须绘制使用该状态的模型部分,切换状态,然后绘制下一个组。
如果您添加更多模型时性能下降,您可以尝试对您的组进行排序,以便在一行中绘制具有相同状态的所有组,而无需切换。
因此,如果您正在绘制100个模型副本,并且模型具有三个组A、B和C:则不这样做:
foreach(model)
set state A;
glDrawArrays(A);
set state B;
glDrawArrays(B);
set state C;
glDrawArrays(C);
你应该这样做:
sort models into groups;
foreach(group)
set state
foreach(instance of group)
glDrawArrays
这样可以节省约99%的状态转换(材质球切换、纹理绑定等)。这将是一个很大的性能改进。
https://stackoverflow.com/questions/11216721
复制相似问题