1

考虑一个由多个对象填充的单个 VBO(或者可能是多个 VBO),每个对象都具有任意顶点数。出于演示目的,假设有一个苹果,有 500 个顶点,一个橙子,有 650 个顶点存储在 VBO 中。

通常,如果我想绘制橙色,我只需调用 glDrawRangeElements 并指出我想绘制元素 500-1150。如果我想在空间中的特定位置绘制橙色,我会使用模型转换。

但是,如果我想绘制可能有数千个对象怎么办?此外,如果 VBO 包含数百个甚至数千个对象作为一种“对象库”呢?我不希望使用即时模式(即,为每个对象手动调用glDrawRangeElements )将我想要绘制的内容传输到我的 GPU 。这将增加与 GPU 通信的大量开销。

我正在寻找的是一种使用 OpenGL 一次性上传某种数组的方法。该数组将包含我要绘制的每个对象的某种标识符,并且可能包含每个对象的转换(位置、旋转)。因此,如果我想在任意位置绘制不同水果的海洋,我只需计算一次索引并上传即可。阵列可以交错。例如,数组可能如下所示:[object id 1 ]、[ position 1 ]、[rotation 1 ] ... [object id n ]。

4

2 回答 2

3

最终,您尝试做的事情(绘制许多完全不同的对象)不适用于任何“实例化”。

实例化适用于相同的对象。即在不同位置绘制的重复对象。您所做的只是绘制许多不同的对象。为此,您将不得不发出多个绘图调用。这是无法避免的。

你能做的最好的就是最小化你的状态变化。使用相同的着色器来渲染对象。使用纹理图集,可能在数组纹理中,这样您就不必更改对象之间的纹理。不要使用glVertexAttribPointer(超过初始设置)或更改元素缓冲区。

最后一部分的关键是glDrawElementsBaseVertex. 只要缓冲区对象中的所有对象都使用相同的顶点格式,就可以将它们全部粘贴在同一个缓冲区中,就像一个巨型数组一样。然后使用索引列表将它们分开。基本顶点部分允许您保持索引相对较小。

最终,您想要的只是在对象之间更改对象的模型空间位置。你有很多选择来处理它。

最简单的方法是像往常一样只使用glUniform更改每个对象的模型到相机矩阵。你现在应该知道如何做到这一点了。

稍微复杂一点的是使用一个统一的缓冲区来存储你想要绘制的所有对象的所有模型到相机矩阵。在对象之间,您使用glBindBufferRange绑定该对象的特定矩阵。没有关于这是否会比以前的方法更快或更慢的信息。请注意,对于统一缓冲区的范围,实现具有与实现相关的对齐方式。

现在从技术上讲,GL 4.x 硬件允许您在表示渲染命令的缓冲区对象中创建一些数据,然后使用它进行渲染。这是 4.0 的核心,称为间接渲染。这样做的一般想法是 OpenCL 或一些专门的 GL 着色器进程将数据写入缓冲区对象,客户端代码只需说“渲染他所说的内容”,而不必读回数据并手动发出glDrawElements呼叫。

这对您没有帮助,因为每个呼叫都必须单独发出。即使使用AMD 的多重间接绘图功能,它仍然对您没有帮助,因为您想为每个对象提供不同的变换。并且多重绘制不允许对象之间的不同变换。

于 2012-06-21T17:04:57.620 回答
1

听起来你想要实例化

查看ARB_instanced_arrays/ ARB_draw_instanced。_

这是各种技术的比较

如果您使用的是固定功能管道,那么您就是 SOL :(

于 2012-06-21T15:58:33.907 回答