opengl - 如何有效地在openGL中渲染大量对象?

标签 opengl

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

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

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

最佳答案

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

Therefore my program on each iteration of drawing loop was executing just single line- glDrawArrays. Can the same be done in case of numerous objects or I do need to form all buffers, enable attrib arrays, bind and set active textures, set shader programs and so on on each iteration of drawing loop (that means sending tons of data to video card that should be slow)?



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

您可以使用Vertex Array Objects (VAOs)存储顶点属性指针和启用,因此在绘制时,您可以绑定(bind) 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*(...)

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

一般来说,有两种主要方法可以提高这种渲染循环的性能:
  • 减少状态变化的次数。

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

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

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

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

    关于opengl - 如何有效地在openGL中渲染大量对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37058648/

    相关文章:

    c++ - 在体素引擎中创建 block 网格很慢

    java - 使用 OpenGL 将文本添加到屏幕

    c++ - opengl中如何用鼠标点击获取帧缓冲区中绘制图形的像素信息

    c# - glsl VertexShader/FragmentShader 拒绝在 OpenTk c# 中编译

    c++ - 我的 OpenGL 应用程序适用于 ATI,但不适用于 nNVIDIA pc

    c++ - gluLookAt 似乎产生了错误的观点,OpenGL

    c++ - 没有任何 vbo 输入的顶点着色器输出

    c++ - OpenGL坐标转换屏幕到世界

    c++ - OpenGL - 深度缓冲区在渲染半透明立方体时切出不应该的面

    c++ - 对 `gluOrtho2D' 的 undefined reference