我试图在THREE.js中学习有关性能几何的更多信息,并且已经了解索引BufferGeometry和InstancedBufferGeometry是两种性能最高的几何类型。

到目前为止,我的理解是,在索引的BufferGeometry中,在几何图形中重复使用的顶点仅添加到几何图形一次,并且给定重复使用的顶点的每个实例都通过其在顶点数组中的索引位置进行引用。

我对InstancedBufferGeometry的理解是,此几何允许创建一个对象的“蓝图”,将该对象的顶点的一个副本发送到着色器,然后使用自定义属性来修改蓝图的位置,旋转,缩放等的每个副本。 。[source]

我想更好地理解:在某些情况下,建立索引的BufferGeometry将比InstancedBufferGeometry更具性能。

另外,在InstancedBufferGeometry中,是否必须考虑WebGL最大参数(例如每个网格的最大顶点),以避免使网格太大?如何计算InstancedBufferGeometry中的顶点?

如果有人可以帮助阐明应该使用索引BufferGeometry和InstancedBufferGeometry的情况以及InstancedBufferGeometry的性能上限,我将不胜感激。

最佳答案



是的,通常,BufferGeometries是处理几何数据的最有效方式,因为它们以与通过WebGL与GPU进行通信所使用的格式完全相同的格式存储数据。在渲染之前,任何普通几何都会在内部转换为BufferGeometry。

您对索引和实例化几何的描述也是正确的,但我想指出更多细节:在索引的几何中,GPU如何组装三角形的指令与顶点数据分开,并提供给GPU具有特殊的索引属性(而不是非索引数组的顶点的隐含部分)。



它们在不同级别上执行不同的操作,因此,我认为在许多用例之间进行选择没有多大意义。
实际上,您甚至可以基于带有索引BufferGeometry的“蓝图”几何来创建实例化几何。

让我们深入细节进行解释。通过实例化的几何图形,您可以在一次绘制调用中呈现同一“蓝图”几何图形的多个“克隆”。
第一部分,即蓝图的创建,与渲染单个几何体相同。为此,需要将属性(位置,法线,uv坐标以及可能用于索引几何的索引)传输到GPU。

实例化几何的特殊之处是一些额外的属性(在three.js InstancedBufferAttribute中)。这些控件控制将渲染几何图形的次数,并提供一些特定于实例的值。一个典型的用例是为每个实例实例位置添加一个额外的vec3属性,为四元数添加一个vec4属性。但这确实可以是其他任何事情。

在顶点着色器中,这些特殊属性看起来与任何其他属性一样,并且您需要手动为每个顶点应用特定于实例的更新。所以代替这个:

attribute vec3 position;
void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

您将具有以下内容:
attribute vec3 position;
attribute vec3 instanceOffset; // this is the InstancedBufferAttribute
void main() {
  gl_Position =
    projectionMatrix
    * modelViewMatrix
    * vec4(position + instanceOffset, 1.0);
}

您在这里看不到的是,实例化版本中的顶点着色器不仅将对几何图形的每个顶点调用一次(常规渲染就是这种情况),而且还将对每个顶点和实例调用一次。

因此,实际上并没有发生任何魔术,实例化几何实际上只是表达整个几何的重复的一种非常有效的方法。



我不确定,但是到目前为止我还没有遇到。如果您知道渲染具有1000个顶点的对象的1000个实例将调用一百万次顶点着色器,这将有助于您判断性能影响。



您可以(也许应该)对几乎任何种类的几何图形都使用索引几何图形。但是它们并非没有缺点:
  • 在使用索引时,所有属性将得到相同的处理。因此,例如,您不能在索引的几何图形中使用按面颜色(请参见Access to faces in BufferGeometry)
  • 对于点云或具有很少重复顶点的几何图形,它们的弊大于利(由于索引需要额外的内存/带宽)

  • 在大多数情况下,尽管它们会获得性能上的好处:
  • 减少顶点数据所需的内存/带宽
  • GPU可以缓存顶点着色器的结果,并将其用于重复的顶点(因此,在最佳情况下,每个存储的顶点而不是每个索引最终将获得一个VS调用)

  • 例如几何
  • 如果您有大量相似的对象(其中差异仅用几个数字即可表示),请使用实例化的几何图形(简单情况:在不同位置渲染同一对象的副本,复杂情况:通过更改基于某些实例属性的树的几何形状,或通过使用实例属性更改单个人的姿势来渲染人群
  • 我发现另一个令人鼓舞的事情:使用实例化渲染粗线:使用实例化渲染一堆线段,其中每个线段由6个三角形组成(请参阅@WestLangley的https://github.com/mrdoob/three.js/blob/dev/examples/js/lines/LineSegmentsGeometry.js)

  • 缺点:
  • 就像现在一样,没有内置支持将常规 Material 与实例化几何一起使用。您必须自己编写着色器。 (确切地说:有一种方法可以做到,但是它需要对three.js着色器的工作原理有深入的了解)。
  • 09-18 00:01