【问题标题】:How to render numerous objects in openGL efficiently?如何有效地在openGL中渲染大量对象?
【发布时间】:2016-05-05 19:20:34
【问题描述】:

这个问题很宽泛,所以我会尽量做到准确。

我编写了一个程序,它只加载和渲染一个具有多个纹理的模型。由于我使用单个模型,我能够形成所有缓冲区、启用所有顶点属性数组、绑定所有顶点数组以及在负责绘制的循环之前绑定和设置活动纹理一次。

因此,我的程序在绘图循环的每次迭代中都只执行单行 glDrawArrays。在有大量对象的情况下是否可以这样做,或者我确实需要在绘图循环的每次迭代中形成所有缓冲区、启用属性数组、绑定和设置活动纹理、设置着色器程序等等(这意味着将大量数据发送到视频应该很慢的卡)?

【问题讨论】:

标签: opengl


【解决方案1】:

目前尚不清楚您到底在寻找什么 - 以及我们在谈论多少对象。

因此,我的程序在绘图循环的每次迭代中都只执行单行-glDrawArrays。在有大量对象的情况下是否可以这样做,或者我确实需要在绘图循环的每次迭代中形成所有缓冲区、启用属性数组、绑定和设置活动纹理、设置着色器程序等等(这意味着将大量数据发送到视频应该很慢的卡)?

是的,那会很慢。缓冲区对象允许您以 GL 可访问的方式存储数据。在理想情况下,GL 可以决定将数据直接存储在 VRAM 中(尽管您永远无法完全控制 OpenGL)。因此,如果您有静态、不变的网格数据,则上传一次是可行的方法。将许多小对象的数据合并到一个缓冲区中也可能很有用。

您可以使用Vertex Array Objects (VAOs) 存储顶点属性指针并启用,因此在绘制时,您可以绑定VAO 并发出绘制调用。因此,渲染多个对象的基本方法是

// ... at initinialization
for each object:
    create and upload VBO(s) and index buffers
    create and upload textures
    create and initialize VAO

// at draw time
for each object:
    bind VAO
    bind texture(s)
    set all other object-related OpenGL state
    (like switching programs, setting unforms for
     the model matrix, base colors, ...)
    glDraw*(...)

如果每帧只绘制几百个对象,使用此方法可能不会遇到性能问题。 (这里不要误会我的意思,我在这里只讨论每个对象的单个绘制调用的开销,而不是实际对象的渲染成本 - 如果你的对象有数百万个顶点,或者你正在生成大量片段,你仍然可以用很少或单个对象降低性能。在这种情况下,你需要一个更聪明的策略来有效地渲染你的对象本身,例如通过应用细节级别方法)

一般来说,有两种主要方法可以提高这种渲染循环的性能:

  1. 减少状态变化的次数。

    切换不同的 GL 状态意味着性能损失。 标准方法是将对象分组 着色器程序,纹理等,您可以绘制多个 对象之间没有昂贵的状态切换。

    查看this answer to a related question 了解不同状态更改的相对成本。

  2. 增加单个绘制调用绘制的对象数量。 在某种程度上,这也意味着方法 1,因为您无法切换 绘图调用期间的 OpenGL 状态。但是,使用现代 GL,您可以例如使用数组纹理并将不同对象的纹理放入单个纹理对象中(您也可以通过使用纹理图集在没有纹理数组的情况下做到这一点,并且可以将两者结合起来)。

    这方面其他非常有趣的功能是

    • instanced rendering(渲染同一对象的多个实例,每个实例的某些属性有所不同,例如模型矩阵)
    • indirect rendering(将多个绘图调用的参数放入另一个缓冲区并通过单个 glMultiDrawElementsIndirect() 调用执行它。由于源数据来自缓冲区对象,因此您可以将其用于生成绘图调用的参数直接在 GPU 上运行,例如通过计算着色器。

近年来,已经提出了一些有效渲染许多对象的策略,这些策略被称为Approaching Zero Driver Overhead (AZDO)

【讨论】:

  • 谢谢!非常有用的信息。你只是读懂了我的想法,甚至回答了我没有包括在内的问题,因为我想让问题简短:) 例如,我在徘徊如何在 OpenGL 中处理有限的纹理,你很好地阐明了这一点,我很好奇VRAM 内容的控制级别,不知何故你也清楚地说明了这一点。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 2014-05-21
相关资源
最近更新 更多