Three.js 索引 BufferGeometry 与 InstancedBufferGeometry [英] Three.js indexed BufferGeometry vs. InstancedBufferGeometry

查看:58
本文介绍了Three.js 索引 BufferGeometry 与 InstancedBufferGeometry的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to learn more about performant geometries in THREE.js, and have come to understand that an indexed BufferGeometry and InstancedBufferGeometry are the two most performant geometry types.

到目前为止,我的理解是,在索引的 BufferGeometry 中,几何中重复使用的顶点只会添加到几何中一次,并且给定重复使用的顶点的每个实例都由它们在顶点中的索引位置引用数组.

My understanding so far is that in an indexed BufferGeometry, vertices that are re-used in a geometry are only added to the geometry once, and each instance of a given re-used vertex are referenced by their index position in the vertex array.

我对 InstancedBufferGeometry 的理解是,该几何体允许创建对象的蓝图",将该对象顶点的一个副本发送到着色器,然后使用自定义属性来修改蓝图的每个副本的位置、旋转、规模等 [来源]

My understanding of the InstancedBufferGeometry is that this geometry allows one to create a "blueprint" of an object, send one copy of that object's vertices to a shader, then use custom attributes to modify each copy of the blueprint's position, rotation, scale, etc. [source]

我想更好地理解:是否存在索引 BufferGeometry 比 InstancedBufferGeometry 性能更高的情况.

I'd like to better understand: are there cases in which an indexed BufferGeometry will be more performant than the InstancedBufferGeometry.

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

Also, in the InstancedBufferGeometry, are there WebGL maximum parameters (such as maximum vertices per mesh) that one must consider so as to avoid making a mesh too large? How are the vertices in an InstancedBufferGeometry counted?

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

If anyone could help clarify the situations in which indexed BufferGeometry and InstancedBufferGeometry should be used, and the performance ceilings of InstancedBufferGeometry, I'd be very grateful.

推荐答案

[...] IndexedBufferGeometry 和 InstancedBufferGeometry 是两种性能最好的几何类型.

[...] IndexedBufferGeometry and InstancedBufferGeometry are the two most performant geometry types.

是的,BufferGeometries 通常是处理几何数据的最高效方式,因为它们以与通过 WebGL 与 GPU 通信时使用的格式存储数据.任何普通的 Geometry 在渲染之前都会在内部转换为 BufferGeometry.

Yes, BufferGeometries in general are the most performant way to deal with geometry-data as they store data in exactly the format that is used in the communication with the GPU via WebGL. Any plain Geometry is internally converted to a BufferGeometry before rendering.

您对索引几何和实例几何的描述也是正确的,但我想注意一个细节:在索引几何中,GPU 如何组装三角形的指令与顶点数据分开并以特殊的索引属性呈现给 GPU(而不是作为非索引数组的顶点的隐含部分).

You are also correct in your descriptions of the indexed and instanced geometries, but I'd like to note one more detail: In an indexed geometry, the instructions for the GPU how to assemble the triangles are separated from the vertex-data and presented to the GPU in a special index-attribute (as opposed to being an implied part of the vertices for non-indexed arrays).

我想更好地理解:是否存在 IndexedBufferGeometry 比 InstancedBufferGeometry 性能更高的情况.

I'd like to better understand: are there cases in which an IndexedBufferGeometry will be more performant than the InstancedBufferGeometry.

它们在不同的层次上做不同的事情,所以我认为没有很多用例可以在它们之间进行选择.事实上,您甚至可以基于具有索引 BufferGeometry 的蓝图"几何体创建实例化几何体.

They do different things at different levels, so I don't think there are many use-cases where a choice between them makes much sense. In fact, you can even create an instanced geometry based on a "blueprint"-geometry that has is an indexed BufferGeometry.

让我们深入了解细节以进行解释.实例化几何体允许您在单个绘制调用中渲染同一蓝图"几何体的多个克隆".第一部分,即蓝图的创建,与渲染单个几何体相同.为此,需要将属性(位置、法线、uv 坐标以及索引几何的索引)传输到 GPU.

Let's dive a bit into the details to explain. An instanced geometry allows you to render multiple "clones" of the same "blueprint"-geometry in a single draw-call. The first part of this, the creation of the blueprint, is identical to rendering a single geometry. For this, the attributes (positions, normals, uv-coordinates and possibly the index for an indexed geometry) need to be transferred to the GPU.

实例几何的特殊之处在于一些额外的属性(在three.js InstancedBufferAttribute 中).这些控制几何图形将被渲染的次数并提供一些特定于实例的值.一个典型的用例是每个实例的实例位置都有一个额外的 vec3-attribute,四元数有一个 vec4-attribute.但它也可以是其他任何东西.

The special thing for instanced geometries are some extra attributes (in three.js InstancedBufferAttribute). These control how many times the geometry will be rendered and provide some instance-specific values. A typical use-case would be to have an additional vec3-attribute for the instance-position and a vec4-attribute for the quaternion per instance. But it really could be anything else as well.

在顶点着色器中,这些特殊属性看起来就像任何其他属性一样,您需要手动应用每个顶点的特定于实例的更新.所以,而不是这样:

In the vertex-shader, these special attributes look just like any other attribute and you need to manually apply the instance-specific updates per vertex. So instead of this:

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);
}

您在这里没有看到的是,实例化版本中的顶点着色器不仅会在几何体的每个顶点调用一次(就像常规渲染的情况一样),而且每个顶点和实例都会调用一次.

What you don't see here is that the vertex-shader in the instanced version will not only be called once per vertex of your geometry (as it is the case for regular rendering) but once per vertex and instance.

所以实际上并没有什么神奇之处,实例化几何实际上只是一种表达整个几何重复的非常有效的方式.

So there isn't actually any magic going on, instanced geometries are in fact nothing but a very efficient way to express duplication of entire geometries.

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

Also, in the InstancedBufferGeometry, are there WebGL maximum parameters (such as maximum vertices per mesh) that one must consider so as to avoid making a mesh too large?

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

I am not sure about that, but I didn't encounter any so far. If you are aware that rendering 1000 instances of an object with 1000 vertices will invoke the vertex-shader a million times that should help your judgement of performance implications.

如果有人能帮助澄清应该使用 IndexedBufferGeometry 和 InstancedBufferGeometry 的情况,以及 InstancedBufferGeometry 的性能上限,我将不胜感激.

If anyone could help clarify the situations in which IndexedBufferGeometry and InstancedBufferGeometry should be used, and the performance ceilings of InstancedBufferGeometry, I'd be very grateful.

您可以(或许应该)为几乎任何类型的几何体使用索引几何体.但它们并非没有缺点:

You can (and maybe should) use indexed geometries for almost any kind of geometry. But they are not free of drawbacks:

  • 使用索引时,所有属性都将得到相同的处理.因此,例如,您不能在索引几何中使用每面颜色(请参阅 访问 BufferGeometry 中的人脸)
  • 对于具有很少重复顶点的点云或几何图形,它们弊大于利(由于索引需要额外的内存/带宽)

大多数情况下,虽然他们会获得性能优势:

most of the time though they will get a performance-benefit:

  • 顶点数据所需的内存/带宽更少
  • GPU 可以缓存顶点着色器的结果并将它们重新用于重复顶点(因此,在最佳情况下,您最终会为每个存储的顶点而不是每个索引进行一次 VS 调用)

例如几何图形

  • 如果您有大量有些相似的对象,其中的差异可以用几个数字来表示,请使用实例几何图形(简单情况:在不同位置渲染同一对象的副本,复杂情况:通过以下方式渲染森林根据某些实例属性更改树的几何形状或通过使用实例属性更改个人姿势来渲染一群人)
  • 我发现另一件非常鼓舞人心的事情:使用实例化渲染粗线:使用实例化渲染一堆线段,其中每个线段由 6 个三角形组成(参见 https://github.com/mrdoob/three.js/blob/dev/examples/js/lines/LineSegmentsGeometry.js by @WestLangley)
  • if you have a larger number of somewhat similar objects where the differences can be expressed in just a few numbers, go for instanced geometries (simple case: render copies of the same object at different locations, complex case: render a forest by changing the tree's geometry based on some instance-attribute or render a crowd of people by changing the individual persons pose with an instance-attribute)
  • another thing I found quite inspiring: rendering of fat lines using instancing: use instancing to render a bunch of line-segments where each line-segment consists of 6 triangles (see https://github.com/mrdoob/three.js/blob/dev/examples/js/lines/LineSegmentsGeometry.js by @WestLangley)

缺点:

  • 就目前而言,没有内置支持将常规材料与实例化几何体一起使用.您必须自己编写着色器.(准确地说:有一种方法可以做到,但它需要对three.js 着色器的工作原理有一些深入了解.

这篇关于Three.js 索引 BufferGeometry 与 InstancedBufferGeometry的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆