mesh_lod.rst 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. .. _doc_mesh_lod:
  2. Mesh level of detail (LOD)
  3. ==========================
  4. Level of detail (LOD) is one of the most important ways to optimize rendering
  5. performance in a 3D project, along with :ref:`doc_occlusion_culling`.
  6. On this page, you'll learn:
  7. - How mesh LOD can improve your 3D project's rendering performance.
  8. - How to set up mesh LOD in Godot.
  9. - How to measure mesh LOD's effectiveness in your project
  10. (and alternatives you can explore if it doesn't meet your expectations).
  11. .. seealso::
  12. You can see how mesh LOD works in action using the
  13. `Occlusion Culling and Mesh LOD demo project <https://github.com/godotengine/godot-demo-projects/tree/master/3d/occlusion_culling_mesh_lod>`__.
  14. Introduction
  15. ------------
  16. Historically, level of detail in 3D games involved manually authoring meshes
  17. with lower geometry density, then configuring the distance thresholds at which
  18. these lower-detailed meshes should be drawn. This approach is still used today
  19. when increased control is needed.
  20. However, in projects that have a large amount of detailed 3D assets, setting up
  21. LOD manually can be a very time-consuming process. As a result, automatic mesh
  22. decimation and LOD configuration is becoming increasingly popular.
  23. Godot provides a way to automatically generate less detailed meshes for LOD
  24. usage on import, then use those LOD meshes when needed automatically. This is
  25. completely transparent to the user.
  26. The `meshoptimizer <https://meshoptimizer.org/>`__ library is used for LOD mesh
  27. generation behind the scenes.
  28. Mesh LOD works with any node that draws 3D meshes. This includes MeshInstance3D,
  29. MultiMeshInstance3D, GPUParticles3D and CPUParticles3D.
  30. Visual comparison
  31. -----------------
  32. Here is an example of LOD meshes generated on import. Lower detailed meshes
  33. will be used when the camera is far away from the object:
  34. .. figure:: img/mesh_lod_comparison_shaded.png
  35. :align: center
  36. :alt: From most detailed (left) to least detailed (right), shaded view
  37. From most detailed (left) to least detailed (right), shaded view
  38. Here's the same image with wireframe rendering to make the decimation easier to see:
  39. .. figure:: img/mesh_lod_comparison_wireframe.png
  40. :align: center
  41. :alt: From most detailed (left) to least detailed (right), wireframe view
  42. From most detailed (left) to least detailed (right), wireframe view
  43. .. seealso::
  44. If you need to manually configure level of detail with artist-created meshes,
  45. use :ref:`doc_visibility_ranges` instead of automatic mesh LOD.
  46. Generating mesh LOD
  47. -------------------
  48. By default, mesh LOD generation happens automatically for imported 3D scenes
  49. (glTF, .blend, Collada, FBX). Once LOD meshes are generated, they will
  50. automatically be used when rendering the scene. You don't need to configure
  51. anything manually.
  52. However, mesh LOD generation does **not** automatically happen for imported 3D
  53. meshes (OBJ). This is because OBJ files are not imported as full 3D scenes by
  54. default, but only as individual mesh resources to load into a MeshInstance3D
  55. node (or GPUParticles3D, CPUParticles3D, ...).
  56. To make an OBJ file have mesh LOD generated for it, select it in the FileSystem
  57. dock, go to the Import dock, change its **Import As** option to **Scene** then
  58. click **Reimport**:
  59. .. figure:: img/mesh_lod_obj_import.png
  60. :align: center
  61. :alt: Changing the import type on an OBJ file in the Import dock
  62. Changing the import type on an OBJ file in the Import dock
  63. This will require restarting the editor after clicking **Reimport**.
  64. .. note::
  65. The mesh LOD generation process is not perfect, and may occasionally
  66. introduce rendering issues (especially in skinned meshes). Mesh LOD
  67. generation can also take a while on complex meshes.
  68. If mesh LOD causes a specific mesh to look broken, you can disable LOD
  69. generation for it in the Import dock. This will also speed up resource
  70. importing. This can be done globally in the 3D scene's import options, or on
  71. a per-mesh basis using the Advanced Import Settings dialog.
  72. See :ref:`Importing 3D scenes <doc_importing_3d_scenes_using_the_import_dock>`
  73. for more information.
  74. Comparing mesh LOD visuals and performance
  75. ------------------------------------------
  76. To disable mesh LOD in the editor for comparison purposes, use the
  77. **Disable Mesh LOD** advanced debug draw mode. This can be done using the menu
  78. in the top-left corner of the 3D viewport (labeled **Perspective** or
  79. **Orthogonal** depending on camera mode):
  80. .. figure:: img/mesh_lod_disable_lod.png
  81. :align: center
  82. :alt: Disabling mesh LOD in the 3D viewport's top-left menu
  83. Disabling mesh LOD in the 3D viewport's top-left menu
  84. Enable **View Frame Time** in the same menu to view FPS in the top-right corner.
  85. Also enable **View Information** in the same menu to view the number of primitives
  86. (vertices + indices) rendered in the bottom-right corner.
  87. If mesh LOD is working correctly in your scene and your camera is far away
  88. enough from the mesh, you should notice the number of drawn primitives
  89. decreasing and FPS increasing when mesh LOD is left enabled (unless you are
  90. CPU-bottlenecked).
  91. To see mesh LOD decimation in action, change the debug draw mode to
  92. **Display Wireframe** in the menu specified above, then adjust the
  93. **Rendering > Mesh LOD > LOD Change > Threshold Pixels** project setting.
  94. Configuring mesh LOD performance and quality
  95. --------------------------------------------
  96. You can adjust how aggressive mesh LOD transitions should be in the root viewport
  97. by changing the **Rendering > Mesh LOD > LOD Change > Threshold Pixels** project
  98. setting. To change this value at run-time, set ``mesh_lod_threshold`` on the
  99. root viewport as follows:
  100. .. tabs::
  101. .. code-tab:: gdscript
  102. get_tree().root.mesh_lod_threshold = 4.0
  103. .. code-tab:: csharp
  104. GetTree().Root.MeshLodThreshold = 4.0f;
  105. Each viewport has its own ``mesh_lod_threshold`` property, which can be set
  106. independently from other viewports.
  107. The default mesh LOD threshold of 1 pixel is tuned to look *perceptually*
  108. lossless; it provides a significant performance gain with an unnoticeable loss
  109. in quality. Higher values will make LOD transitions happen sooner when the
  110. camera moves away, resulting in higher performance but lower quality.
  111. If you need to perform per-object adjustments to mesh LOD, you can adjust how
  112. aggressive LOD transitions should be by adjusting the **LOD Bias** property on
  113. any node that inherits from GeometryInstance3D. Values *above* ``1.0`` will make
  114. LOD transitions happen later than usual (resulting in higher quality but lower
  115. performance). Values *below* ``1.0`` will make LOD transitions happen sooner than
  116. usual (resulting in lower quality but higher performance).
  117. Additionally, ReflectionProbe nodes have their own **Mesh LOD Threshold** property
  118. that can be adjusted to improve rendering performance when the reflection probe
  119. updates. This is especially important for ReflectionProbes that use the **Always**
  120. update mode.
  121. .. note::
  122. When rendering the scene, mesh LOD selection uses a screen-space metric.
  123. This means it automatically takes camera field of view and viewport
  124. resolution into account. Higher camera FOV and lower viewport resolutions
  125. will make LOD selection more aggressive; the engine will display heavily
  126. decimated models earlier when the camera moves away.
  127. As a result, unlike :ref:`doc_visibility_ranges`, you don't need to do
  128. anything specific in your project to take camera FOV and viewport resolution
  129. into account.
  130. Using mesh LOD with MultiMesh and particles
  131. -------------------------------------------
  132. For LOD selection, the point of the node's :abbr:`AABB (Axis-Aligned Bounding Box)`
  133. that is the closest to the camera is used as a basis. This applies to any kind
  134. of mesh LOD (including for individual MeshInstance3D)s, but this has some implications
  135. for nodes that display multiple meshes at once, such as MultiMeshInstance3D,
  136. GPUParticles3D and GPUParticles3D. Most importantly, this means that all
  137. instances will be drawn with the same LOD level at a given time.
  138. If you are noticing incorrect LOD selection with GPUParticles3D, make sure
  139. the node's visibility AABB is configured by selecting the GPUParticles3D
  140. node and using **GPUParticles3D > Generate AABB** at the top of the 3D
  141. viewport.
  142. If you have instances in a MultiMesh that are far away from each other, they
  143. should be placed in a separate MultiMeshInstance3D node. Doing so will also
  144. improve rendering performance, as frustum and occlusion culling will be able to
  145. cull individual nodes (while they can't cull individual instances in a
  146. MultiMesh).