opengl-es - 在 OpenGL ES 中渲染对象组

标签 opengl-es vbo

我是 OpenGL ES 的新手,我正在编写一个 iPad 应用程序,它需要我加载一个 Wavefront Obj 文件,然后在 OpenGL 中绘制它们。我的问题是关于呈现 Obj 文件组的最有效方式。

关于我所拥有的一些背景知识。 Obj 模型的所有解析/加载都在工作(我使用 GLM 加载文件),因此繁琐的事情不在话下。对于基础项目,我在 XCode 中扩展了 OpenGL ES 游戏模板,并删除了对着色器的所有调用。我正在为我的着色器使用 GLKit 的 BaseEffect,并使用 VAO 和 VBO 加载我所有的顶点数据。对于具有 16 个组的模型,在初始时间我将每个组分成一个 VAO,每个 VAO 都有一个用于顶点数据和法线(交错)的 VBO,以及一个用于纹理坐标的第二个 VBO。每个组都有一种 Material (有时是一种纹理,但为了问题的缘故只假设 Material )。

在我的渲染例程(下面的伪代码)中,我循环遍历为每个组创建的所有 VAO,将组的 Material 应用到 BaseEffect,然后使用 DrawArrays 绘制它(不使用 DrawElements 因为我已经设置 VBO 以便数据已经按索引顺序排列,尽管它可能不如在图形内存上高效)。这行得通,我可以用不同的 Material 绘制每个模型,但随着组数的增加,我的帧率下降,因为我必须花更多的时间在我的渲染函数中循环遍历每个组。对于较少的模型数量,这很好,但随着我向应用程序添加更多模型,帧速率远低于 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)   
}

显而易见的答案是简化模型以减少组数,但我很好奇渲染例程是否有任何改进可以让我做同样的事情但减少 Draw 调用。我仍然希望有一个详细的 obj 文件,但也希望有最高效的渲染。

这是绘制 obj 文件的最佳方法吗?我必须为文件中的每个组使用多种 Material /纹理,或者有没有一种方法可以在不遍历每个组并单独绘制它们的情况下完成?我希望能够让每个 obj 模型只有 1 次调用 DrawArrays/DrawElements,但我不知道如何做到这一点并且仍然对对象应用多种 Material /纹理。我一直在看这段代码并想“必须有更好的方法”,但我不确定那是什么。如果我遗漏了一个明显的难题,或者如果您有任何建议可以优化它,我将永远感激不已。

最佳答案

我认为您的想法非常正确。您实际上一次只能有一组纹理或一个着色器处于事件状态,因此您必须绘制模型中使用该状态的部分,切换状态,然后绘制下一组。

如果您的性能随着您添加更多模型而下降,您可以尝试对您的组进行排序,以便在不切换的情况下连续绘制所有具有相同状态的组。

因此,如果您要绘制 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% 的状态转换(着色器切换、纹理绑定(bind)等)。这将是一个很大的性能改进。

关于opengl-es - 在 OpenGL ES 中渲染对象组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11216721/

相关文章:

java - 如何从脸部检测特定物体并实时添加我的图像?

java - 访问 AsyncTask 中的浮点值

opengl - 字符串化 openGL 枚举

c++ - OpenGL:将 VBO 与 std::vector 一起使用

android - OpenGL立方体着色

ios - 片段着色器未读取顶点着色器 'colorVarying' 的输出

c - OpenGL 3.3 - glDrawArrays 之后无效操作错误 (1282)

java - GL_QUADS 和 GL_TRIANGLE STRIP 之间是否存在明显的性能差异?

c - 简单的 VBO 示例存在问题