【问题标题】:OpenGL - Indexed Draws with glDrawElementsOpenGL - 使用 glDrawElements 进行索引绘制
【发布时间】:2014-04-20 21:19:30
【问题描述】:

我有几个关于 OpenGL 如何处理这些绘图操作的问题。

  1. 假设我将 OpenGL 指针传递给我的顶点数组。然后我可以用一组索引调用 glDrawElements。它将使用顶点数组中的那些索引绘制请求的形状正确吗?

  2. 在调用 glDrawElements 之后,我可以使用另一组索引进行另一个 glDawElements 调用吗?然后它会使用原始顶点数组绘制新的索引数组吗?

  3. 当我重做所有这些调用时,OpenGL 是否会为下一帧保留我的顶点数据?那么下一个顶点指针调用会快很多吗?

  4. 假设最后三个问题的答案是肯定的,如果我想在每帧的多个顶点数组上执行此操作怎么办?我假设在超过 1 个顶点数组上执行此操作会导致 OpenGL 从图形内存中删除最后使用的数组并开始使用新的数组。但就我而言,顶点数组永远不会改变。所以我想知道的是opengl是否会保留我的顶点数组,以防下次我发送顶点数据时它会是相同的数据?如果没有,有没有办法可以优化它以允许这样的事情?基本上,我想在不更新顶点数据的情况下使用索引在顶点之间进行程序绘制,以减少开销并加速复杂的渲染,这需要不断变化的形状,这些形状将始终使用原始顶点数组中的顶点。这是可能的还是我只是幻想?

  5. 如果我只是幻想我的第四个问题,有什么好的快速方法可以在每帧中绘制大量多边形而只有少数会改变?即使是很小的变化,我是否总是需要传入一组全新的顶点数据?当顶点数据没有改变时,它是否已经这样做了,因为我注意到我无法真正绕过顶点指针调用每一帧。

  6. 请随意抨击我在断言中犯的任何逻辑错误。我正在尽我所能了解 opengl 的工作原理,我目前对其工作原理的假设完全有可能是错误的。

【问题讨论】:

    标签: c++ opengl vertex-array


    【解决方案1】:

    1.所以假设我将指针传递给 OpenGL 到我的顶点数组。然后我可以用一组索引调用 glDrawElements。它将绘制 使用顶点数组中的这些索引请求的形状正确吗?

    是的。

    2.在那次 glDrawElements 调用之后,我可以再做一个 glDawElements 用另一组索引调用?然后它会绘制新的索引吗 使用原始顶点数组的数组?

    是的。

    3. 当我重做时,OpenGL 是否会为下一帧保留我的顶点数据? 所有这些电话?所以下一个顶点指针调用会很多 更快?

    回答这个问题比你想象的要复杂一些。你问这些问题的方式让我假设你使用客户端顶点数组,也就是说,你的系统内存中有一些数组,让你的顶点指针直接指向那些。在这种情况下,答案是no。 GL 不能以任何有用的方式“缓存”该数据。绘制调用完成后,它必须假设您可能会更改数据,并且必须比较每一位以确保您没有更改任何内容。

    但是,客户端 VA 并不是在 GL 中拥有 VA 的唯一方法 - 实际上,它们已经完全过时,自 GL3.0 以来已被弃用,并且已从现代版本的 OpenGL 中删除。现代的瘦身方法是使用 Vertex Buffer Objects,它们基​​本上是 由 GL 管理但由用户操作的缓冲区。缓冲区对象只是一块内存,但您将需要特殊的 GL 调用来创建它们、读取或写入或更改数据等等。并且缓冲区对象很可能不会存储在系统内存中,而是直接存储在 VRAM 中,这对于反复使用的静态数据非常有用。看看the GL_ARB_vertex_buffer_object extension spec,它最初在 2003 年引入了该功能,并成为 GL 1.5 的核心。

    4.假设最后三个问题的答案是肯定的,如果我想要怎么办 在每帧的多个顶点数组上执行此操作?我假设做 这在任何超过 1 个顶点数组上都会导致 OpenGL 放弃 最后使用图形内存中的数组并开始使用新的数组。但 在我的情况下,顶点数组永远不会改变。所以我想要什么 要知道opengl是否会在下次以防万一的情况下保留我的顶点数组 我向它发送顶点数据,它会是相同的数据吗?如果没有有没有办法 我可以优化它以允许这样的事情吗?基本上我想 使用索引在顶点之间按程序绘制而不更新 顶点数据,为了减少开销和加速复杂 需要不断变化的形状的渲染 将始终使用原始顶点数组中的顶点。这是 可能还是我只是幻想?

    VBO 正是您正在寻找的,在这里。

    5.如果我只是幻想我的第四个问题,有什么好的 每帧绘制大量多边形的快速方法,其中只有一个 有几个会变?我是否总是要通过一套全新的 顶点数据即使是很小的变化?它是否已经这样做了 当顶点数据没有改变时,因为我注意到我不能真正得到 围绕顶点指针调用每一帧。

    您也可以只更新 VBO 的一部分。但是,如果您有许多随机分布在缓冲区中的小部分,它可能会变得低效,更新连续(子)区域会更有效。但这是一个独立的话题。

    【讨论】:

    • 诀窍是:如果我希望我的应用程序兼容 OpenGL 1.1,是否可以使用 VBO?
    • @KlaytonCurran:严格来说,没有什么可以阻止 GL1.1 实现支持该扩展。然而,任何仅限于 GL1.1 的东西都不太可能。请问你为什么只限GL1.1?如果你真的是,display lists 是你唯一的选择。
    • 你回答了我想知道的一切,干净利落,细节丰富。非常感谢! 1.1 的问题主要是出于好奇。
    【解决方案2】:
    1. 是的
    2. 是的
    3. 没有。一旦您创建了顶点缓冲区对象 (VBO),它将保留在 GPU 内存中。否则需要重新传输矢量数据(避免这种情况的旧方法是显示列表)。在这两种情况下,后续帧的性能应该保持相似(但使用 VBO 方法要好得多):您可以在渲染第一帧之前创建和下载 VBO。
    4. 引入 VBO 是为了准确地为您提供此功能。只需创建几个 VBO。但是,当您需要的 GPU 内存超出可用内存时,事情就会变得一团糟。
    5. VBO 仍然是答案,请参阅Modifying only a specific element type of VBO buffer data?

    【讨论】:

    • 谢谢!该链接将很有用。
    【解决方案3】:

    听起来你应该尝试一种叫做顶点缓冲区对象的东西。它提供与顶点数组相同的好处,但您可以创建多个顶点缓冲区并将它们存储在“命名槽”中。由于数据直接存储在显卡内存中,因此这种方法的性能要好得多。

    Here 是一个很好的 C++ 入门教程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      • 2015-10-12
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      相关资源
      最近更新 更多