我试图在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个实例将调用一百万次顶点着色器,这将有助于您判断性能影响。
您可以(也许应该)对几乎任何种类的几何图形都使用索引几何图形。但是它们并非没有缺点:
在大多数情况下,尽管它们会获得性能上的好处:
例如几何
缺点: