在 glTF 格式中, 网格对象位置经历三个间接级别: 网格 -> 访问器 -> bufferView -> 缓冲区。
网格数据应如何在访问器之间分布, glTF 文件中的 bufferView 和缓冲区?有关系吗?
例如假设我有两个网格,每个网格都有一个 POSITION 属性。 看来我基本上有四种布局选择 glTF 文件中的位置数据:
===============================================================
(A) one big shared accessor,bufferView,buffer for all positions
mesh 0 -+
+-> accessor 0 ---> bufferView 0 ---> buffer 0
mesh 1 -+
===============================================================
(B) accessor per mesh, one big shared bufferView,buffer
mesh 0 ---> accessor 0 -+
+-> bufferView 0 ---> buffer 0
mesh 1 ---> accessor 1 -+
===============================================================
(C) accessor,bufferView per mesh, one big shared buffer
mesh 0 ---> accessor 0 ---> bufferView 0 -+
+-> buffer 0
mesh 1 ---> accessor 1 ---> bufferView 1 -+
===============================================================
(D) accessor,bufferView,buffer per mesh
mesh 0 ---> accessor 0 ---> bufferView 0 ---> buffer 0
mesh 1 ---> accessor 1 ---> bufferView 1 ---> buffer 1
===============================================================
在上述四种布局选择中,(A) 生成最简单、最紧凑的 glTF 文件 (特别是如果两个网格共享一些顶点位置)。 所以我不确定为什么我会使用 (B)、(C) 或 (D) 中的任何一个。
我问的原因是我目前正在使用 (A) 创建 glTF 文件 (每个文件包含数千个网格), 但我发现当我 将文件加载到 Three.js 中并使用它。例如:
所以我认为必须有一个假设(由 Threejs 和/或其他消费者 glTF 文件),我正在使用 (B)、(C) 或 (D) 代替? 但我不知道假设的是什么,或者一般来说我应该使用哪种布局。
我倾向于用这些术语来思考缓冲区和缓冲区视图:
在大多数情况下,您应该只需要一个缓冲区。任何细分通常都是为了特定于应用程序的目的,例如对来自不同网格或动画的数据进行分区,以便可以在不同时间通过网络下载。
理论上,缓冲区视图越少越好。在实践中,大多数 3D 引擎都有限制,会影响最佳选择。 正如您所描述的, Three.js 在跨多个 THREE.BufferGeometry 实例共享顶点数据方面做得不太好。除了边界框问题(可能可以解决!)之外,它目前还会“将每个 BufferGeometry 分别上传到 GPU”,这会重复数据,并且解决起来更加复杂。因此,特别是对于 Three.js,理想的布局可能是每个网格图元一个缓冲区视图,每个网格图元内的顶点属性在该单个缓冲区视图中交错。 因此,虽然引擎的目标是至少支持所有内容,但它们可能针对特定布局进行了“优化”。在实践中,为目标引擎预处理 glTF 文件会很有帮助,以缩短加载时间。 gltfpack 或 glTF Transform 是可以在这里使用的流行工具。
示例:
npm install --global @gltf-transform/cli
# aims for one interleaved buffer view per mesh primitive
gltf-transform cp in.glb out.glb --vertex-layout interleaved
# aims for one buffer view per vertex attribute
gltf-transform cp in.glb out.glb --vertex-layout separate
特定情况(例如压缩或在多个几何图形中共享单个顶点属性)确实使情况变得复杂,并且需要编码器做出更多决策。
三.js r164