OpenGL 将两个不同的网格放在同一个顶点 VBO 中的最佳实践



经过一番搜索,据说分离的VAO共享完全相同的着色器属性布局,将它们合并到一个VAO中,并将所有这些数据放入一个VBO,以便我只需一次绘制调用即可绘制此对象。

这完全有道理,但是均匀变量呢?说我想画树和球。它们具有不同的顶点计数,具有不同的转换,但共享完全相同的着色器程序。

直到现在,我的程序就像

// generate VAOs, called only once
glGenVertexArray(1, &treeVaoId);
// generate VBO and bind tree vertices
// enabled vertex attribute and set it for shader program
glGenVertexArray(1, &ballVaoId);
// repeat for ball

// draw, called each frame
// give the tree's transform to shader as uniform
glDrawArrays(...) // first draw call
// repeat for ball
glDrawArrays(...) // second draw call

将这些顶点到一个 VAO 和 VBO,例如:

glGenVertexArray(1, &treeBallId);
// generate enough size of VBO and bind tree vertices and ball vertices after it.
// enabled vertex attribute and set it for shader program
// to draw, I have to separately give transform to it's uniform to each tree and ball, but how?
glDrawArrays(...)

很抱歉这个糟糕的例子,但关键是,有没有办法在绘制一个 VAO 时给出不同的统一变量?或者,我的方法完全错误吗?

批处理的目的是通过最小化绘制调用之间的状态更改来提高性能(批处理将它们减少到 0,因为绘制调用之间没有任何内容)。但是,存在一定程度的性能改进,并且并非所有状态更改都是相同的。

在国家变化的成本规模上,改变程序制服是最便宜的国家变化。这并不是说它毫无意义,但你应该考虑与你从中获得的结果相比,你真正想花多少精力。特别是如果您没有尽可能快地推动硬件。

VAO 更改(即非仅缓冲区更改)是成本更高的状态更改之一,因此通过消除它们,您可以获得很多收益。

顾名思义,uniform变量不能在绘制调用中从一个着色器实例更改为另一个着色器实例。甚至是多次抽奖调用。但这并不意味着无能为力。

多重绘制功能允许您在单个函数调用中发出多个绘制调用。这些单独的绘制可以从顶点和索引缓冲区的不同部分获取其顶点数据。您需要的是一种与顶点着色器通信的方法,它正在参与哪个绘制调用,以便它可以索引某种数组以提取该绘制调用的每个对象数据。

半最近的硬件可以访问gl_DrawID,这是正在执行的特定绘制调用的多绘制命令的索引。ARB_shader_draw_parameters扩展得到了相当广泛的实施。您可以使用该索引从 UBO 或 SSBO 获取每个对象的数据。

最新更新