Work in progress

The content of this page was not yet updated for Godot 4.2 and may be outdated. If you know how to improve this page or you can confirm that it’s up to date, feel free to open a pull request.

使用 MultiMesh 优化

对于大量的实例(成千上万), 需要不断处理(需要保留一定的控制), 建议优化 直接使用服务 .

当对象数量达到数十万或数百万时, 这些方法都不再有效. 尽管如此, 根据要求, 还有另一种可能的优化方法.

MultiMesh

MultiMesh 是一个单次绘制的图元,可以一次性绘制多达数百万个对象。它的效率非常高,因为它使用 GPU 硬件来做这件事(不过在 OpenGL ES 2.0 中,它的效率较低,因为没有硬件支持)。

唯一的缺点是, 对于单个实例, 不可能进行 屏幕视锥 剔除. 这意味着, 根据整个MultiMesh的可见性, 数百万个对象将被 始终不会 绘制. 可以为它们提供一个自定义的可见性矩形, 但它将始终是 全或无 的可见性.

如果对象足够简单(只有几个顶点), 这通常不是什么大问题, 因为大多数现代GPU都为这种用例进行了优化. 一个变通的方法是为世界的不同区域创建多个MultiMeshes.

也可以在顶点着色器中执行一些逻辑(使用 INSTANCE_IDINSTANCE_CUSTOM 内置常量). 关于在MultiMesh中对数千个对象进行动画制作的例子, 请参见 Animating thousands of fish 教程. 可以通过纹理向着色器提供信息(有浮点 Image 格式是理想的格式).

Another alternative is to use a GDExtension and C++, which should be extremely efficient (it’s possible to set the entire state for all objects using linear memory via the RenderingServer.multimesh_set_buffer() function). This way, the array can be created with multiple threads, then set in one call, providing high cache efficiency.

最后, 并不是所有的MultiMesh实例都必须是可见的. 可以通过 MultiMesh.visible_instance_count 属性来控制可见的数量. 典型的工作流程是先分配最大数量的实例, 然后根据当前需要的数量改变可见的数量.

多重网格示例

这里是一个从代码中使用MultiMesh的例子.GDScript以外的其他语言对于数百万个对象来说可能更有效, 但对于几千个对象来说,GDScript应该是可以的.

GDScriptC#

  1. extends MultiMeshInstance3D
  2. func _ready():
  3. # Create the multimesh.
  4. multimesh = MultiMesh.new()
  5. # Set the format first.
  6. multimesh.transform_format = MultiMesh.TRANSFORM_3D
  7. # Then resize (otherwise, changing the format is not allowed).
  8. multimesh.instance_count = 10000
  9. # Maybe not all of them should be visible at first.
  10. multimesh.visible_instance_count = 1000
  11. # Set the transform of the instances.
  12. for i in multimesh.visible_instance_count:
  13. multimesh.set_instance_transform(i, Transform3D(Basis(), Vector3(i * 20, 0, 0)))
  1. using Godot;
  2. public partial class MyMultiMeshInstance3D : MultiMeshInstance3D
  3. {
  4. public override void _Ready()
  5. {
  6. // Create the multimesh.
  7. Multimesh = new MultiMesh();
  8. // Set the format first.
  9. Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
  10. // Then resize (otherwise, changing the format is not allowed)
  11. Multimesh.InstanceCount = 1000;
  12. // Maybe not all of them should be visible at first.
  13. Multimesh.VisibleInstanceCount = 1000;
  14. // Set the transform of the instances.
  15. for (int i = 0; i < Multimesh.VisibleInstanceCount; i++)
  16. {
  17. Multimesh.SetInstanceTransform(i, new Transform3D(Basis.Identity, new Vector3(i * 20, 0, 0)));
  18. }
  19. }
  20. }

Previous Next


© 版权所有 2014-present Juan Linietsky, Ariel Manzur and the Godot community (CC BY 3.0). Revision b1c660f7.

Built with Sphinx using a theme provided by Read the Docs.