首页 文章

使用OpenGL着色器渲染多个对象

提问于
浏览
0

在带着色器的OpenGL中,我想渲染两个已加载为两个网格的对象 . 每个对象由一组顶点位置,一组顶点颜色和一组三角形的顶点索引表示 .

我可以通过三种方式来绘制这两个对象 . 哪种是最佳做法?

1)我将两个对象的顶点位置连接成一个长的顶点数组,并且类似于顶点颜色和顶点索引 . 然后我创建一个顶点位置缓冲区,一个顶点颜色缓冲区和一个索引缓冲区 . 渲染时,我然后调用 glBindBuffer(...)glDrawElements(...) .

2)我将两个对象的顶点位置连接成一个长的顶点数组,并且类似于顶点颜色 . 然后我创建一个顶点位置缓冲区和一个顶点颜色缓冲区 . 渲染时,我然后对 glBindBuffer(...)glDrawElements(...) 进行两次调用,每个对象一次 .

3)我创建了两个顶点位置缓冲区,两个顶点颜色缓冲区和两个索引缓冲区 . 渲染时,我然后对 glBindBuffer(...)glDrawElements(...) 进行两次调用,每个对象一次 .

谢谢!

2 回答

  • 1

    OpenGL优化的一般规则是最小化状态更改的数量 . 绑定缓冲区是状态变化 .

    所以,在所有其他条件相同的情况下,#1可能是最快的 .

    但是,它并不总是特别有用 . 通常,不同的对象相对于彼此具有不同的变换 . 通常,您需要在渲染对象之间更改某些状态,因此#1不是一个选项 .

    即便如此,您也不必使用选项2.您可以使用与选项1相同的缓冲区设置,但只需发出两个绘制调用 . 每个绘制都将使用部分数组进行渲染 .

    同样重要的是,对于顶点数组,问题不在于绑定缓冲区(尽管它们不会改变您使用的vertex format,属性的相对排列 . 如果使用separate attribute format API,您可以轻松更改缓冲区绑定而无需触及格式通常,整个程序中只有5-6个顶点格式 .

    另一个问题是你没有在这里充分探索各种可能性 . 例如,在所有情况下,位置,颜色,法线和其他属性都位于不同的缓冲区中 . 那么......为什么他们在不同的缓冲区? Interleaving your vertex attributes通常会提供更好的性能 .

    所以,最佳表现的答案是“以上都不是” .

  • 1

    只渲染了2个对象,这些选项都不会使您接近任何类型的性能瓶颈 . 如果您的帧速率与显示刷新率(通常约为60 fps)相匹配,则每秒只需渲染120个对象 .

    假设您需要为每个对象提供少量状态设置调用,这使您可以在每秒1000个状态设置调用的范围内 . 虽然性能特征当然是高度平台/供应商特定的,但是中途不错的驱动程序将能够每秒处理几百万个简单的状态设置调用(如绑定缓冲区,设置顶点属性等) . 因此,您至少要比我开始担心吞吐量的水平低3到4个数量级 .

    现在,如果你有数千个对象,事情开始变得有点不同了 . 我肯定会推荐两件事:

    • 使用交错属性 . 这意味着您按顺序存储一个顶点的位置和颜色,然后是下一个顶点的属性 . 假设您有3个组件 (xk, yk, pk) 作为位置,4个组件 (rk, gk, bk, ak) 作为顶点颜色 k ,缓冲区的内存布局是:
    x0 y0 z0 r0 g0 b0 a0 x1 y1 z1 r1 g1 b1 a1 x2 y2 z2 r2 g2 b2 a2 ...
    
    • 使用VAO(顶点阵列对象)设置状态 . 这将允许您使用单个 glBindVertexArray() 调用为对象设置整个顶点属性状态 .

    一般来说,为每个对象分别使用单独的VBO或在对象之间共享更大的VBO更好是否更好 . 拥有大量的小型VBO肯定会对性能产生影响,如果您可以相当容易地进行安排,那么分享它们可能会有所帮助 . 但我也可以想象一下,如果有很大的维生素生态系统会产生不利影响 . 因此,如果您希望在拥有大量对象的情况下获得最大性能,则可能必须尝试不同的选项 . 不幸的是,结果很可能取决于平台 .

相关问题