visibility_ranges.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. .. _doc_visibility_ranges:
  2. Visibility ranges (HLOD)
  3. ========================
  4. Along with :ref:`doc_mesh_lod` and :ref:`doc_occlusion_culling`,
  5. visibility ranges are another tool to improve performance in large,
  6. complex 3D scenes.
  7. On this page, you'll learn:
  8. - What visibility ranges can do and which scenarios they are useful in.
  9. - How to set up visibility ranges (manual LOD) in Godot.
  10. - How to tune visibility ranges for best performance and quality.
  11. .. seealso::
  12. If you only need meshes to become less detailed over distance, but don't have
  13. manually authored LOD meshes, consider relying on automatic
  14. :ref:`doc_mesh_lod` instead.
  15. Note that automatic mesh LOD and visibility ranges can be used at the same
  16. time, even on the same mesh.
  17. How it works
  18. ------------
  19. Visibility ranges can be used with any node that inherits from GeometryInstance3D.
  20. This means they can be used not only with MeshInstance3D and MultiMeshInstance3D
  21. for artist-controlled :abbr:`HLOD (Hierarchical Level of Detail)`, but also
  22. GPUParticles3D, CPUParticles3D, Label3D, Sprite3D, AnimatedSprite3D and CSGShape3D.
  23. Since visibility ranges are configured on a per-node basis, this makes it possible
  24. to use different node types as part of a :abbr:`LOD (Level of Detail)` system.
  25. For example, you could display a MeshInstance3D representing a tree when up close,
  26. and replace it with a Sprite3D impostor in the distance to improve performance.
  27. The benefit of :abbr:`HLOD (Hierarchical Level of Detail)` over a traditional
  28. :abbr:`LOD (Level of Detail)` system is its hierarchical nature. A single larger
  29. mesh can replace several smaller meshes, so that the number of draw calls can be
  30. reduced at a distance, but culling opportunities can be preserved when up close.
  31. For example, you can have a group of houses that uses individual MeshInstance3D
  32. nodes (one for each house) when up close, but turns into a single MeshInstance3D
  33. that represents a less detailed group of houses (or use a MultiMeshInstance3D).
  34. Lastly, visibility ranges can also be used to fade certain objects entirely when
  35. the camera gets too close or too far. This can be used for gameplay purposes,
  36. but also to reduce visual clutter. For example, Label3D nodes can be faded using
  37. visibility ranges when they're too far away to be readable or relevant to the
  38. player.
  39. Setting up visibility range
  40. ---------------------------
  41. This is a quick-start guide for configuring a basic LOD system. After following
  42. this guide, this LOD system will display a SphereMesh when up close and a
  43. BoxMesh when the camera is far away enough. A small hysteresis margin is also
  44. configured via the **Begin Margin** and **End Margin** properties. This prevents
  45. LODs from popping back and forth too quickly when the camera is moving at the
  46. "edge" of the LOD transition.
  47. The visibility range properties can be found in the **Visibility Range** section
  48. of the GeometryInstance3D inspector after selecting the MeshInstance3D Node.
  49. - Add a Node3D node that will be used to group the two MeshInstance3D nodes
  50. together.
  51. - Add a first MeshInstance3D node as a child of the Node3D. Assign a new
  52. SphereMesh to its Mesh property.
  53. - Set the first MeshInstance3D's visibility range **End** to ``10.0`` and **End
  54. Margin** to ``1.0``.
  55. - Add a second MeshInstance3D node as a child of the Node3D. Assign a new
  56. BoxMesh to its Mesh property.
  57. - Set the second MeshInstance3D's visibility range **Begin** to ``10.0`` and
  58. **Begin Margin** to ``1.0``.
  59. - Move the camera away and back towards the object. Notice how the object will
  60. transition from a sphere to a box as the camera moves away.
  61. Visibility range properties
  62. ---------------------------
  63. In the inspector of any node that inherits from GeometryInstance3D, you can adjust
  64. the following properties in the GeometryInstance3D's **Visibility Range** section:
  65. - **Begin:** The instance will be hidden when the camera is closer to the
  66. instance's *origin* than this value (in 3D units).
  67. - **Begin Margin:** The hysteresis or alpha fade transition distance to use for
  68. the close-up transition (in 3D units). The behavior of this property depends
  69. on **Fade Mode**.
  70. - **End:** The instance will be hidden when the camera is further away from the
  71. instance's *origin* than this value (in 3D units).
  72. - **End Margin:** The hysteresis or alpha fade transition distance to use for
  73. the far-away transition (in 3D units). The behavior of this property depends
  74. on **Fade Mode**.
  75. - **Fade Mode:** Controls how the transition between LOD levels should be performed.
  76. See below for details.
  77. .. _doc_visibility_ranges_fade_mode:
  78. Fade mode
  79. ^^^^^^^^^
  80. .. note::
  81. The fade mode chosen only has a visible impact if either
  82. **Visibility Range > Begin Margin** or **Visibility Range > End Margin** is
  83. greater than ``0.0``.
  84. In the inspector's **Visibility Range** section, there are 3 fade modes to
  85. choose from:
  86. - **Disabled:** Uses hysteresis to switch between LOD levels instantly. This
  87. prevents situations where LOD levels are switched back and forth quickly when
  88. the player moves forward and then backward at the LOD transition point. The
  89. hysteresis distance is determined by **Visibility Range > Begin Margin** and
  90. **Visibility Range > End Margin**. This mode provides the best performance as
  91. it doesn't force rendering to become transparent during the fade transition.
  92. - **Self:** Uses alpha blending to smoothly fade between LOD levels. The node
  93. will fade-out itself when reaching the limits of its own visibility range. The
  94. fade transition distance is determined by **Visibility Range > Begin Margin**
  95. and **Visibility Range > End Margin**. This mode forces transparent rendering
  96. on the object during its fade transition, so it has a performance impact.
  97. - **Dependencies:** Uses alpha blending to smoothly fade between LOD levels. The
  98. node will fade-in its dependencies when reaching the limits of its own
  99. visibility range. The fade transition distance is determined by **Visibility
  100. Range > Begin Margin** and **Visibility Range > End Margin**. This mode forces
  101. transparent rendering on the object during its fade transition, so it has a
  102. performance impact. This mode is intended for hierarchical LOD systems using
  103. :ref:`Visibility parent <doc_visibility_ranges_visibility_parent>`. It acts
  104. the same as **Self** if visibility ranges are used to perform non-hierarchical
  105. LOD.
  106. .. _doc_visibility_ranges_visibility_parent:
  107. Visibility parent
  108. ^^^^^^^^^^^^^^^^^
  109. The **Visibility Parent** property makes it easier to set up
  110. :abbr:`HLOD (Hierarchical Level of Detail)`. It allows automatically hiding
  111. child nodes if its parent is visible given its current visibility range properties.
  112. .. note::
  113. The target of **Visibility Parent** *must* inherit from
  114. :ref:`class_GeometryInstance3D`.
  115. Despite its name, the **Visibility Parent** property *can* point to a node
  116. that is not a parent of the node in the scene tree. However, it is
  117. impossible to point **Visibility Parent** towards a child node, as this
  118. creates a dependency cycle which is not supported. You will get an error
  119. message in the Output panel if a dependency cycle occurs.
  120. Given the following scene tree (where all nodes inherit from GeometryInstance3D):
  121. ::
  122. ┖╴BatchOfHouses
  123. ┠╴House1
  124. ┠╴House2
  125. ┠╴House3
  126. ┖╴House4
  127. In this example, *BatchOfHouses* is a large mesh designed to represent all child
  128. nodes when viewed at a distance. *House1* to *House4* are smaller
  129. MeshInstance3Ds representing individual houses. To configure HLOD in this
  130. example, we only need to configure two things:
  131. - Set **Visibility Range Begin** to a number greater than `0.0` so that
  132. *BatchOfHouses* only appears when far away enough from the camera. Below this
  133. distance, we want *House1* to *House4* to be displayed instead.
  134. - On *House1* to *House4*, assign the **Visibility Parent** property to *BatchOfHouses*.
  135. This makes it easier to perform further adjustments, as you don't need to adjust
  136. the **Visibility Range Begin** of *BatchOfHouses* and **Visibility Range End**
  137. of *House1* to *House4*.
  138. Fade mode is automatically handled by the **Visibility Parent** property, so
  139. that the child nodes only become hidden once the parent node is fully faded out.
  140. This is done to minimize visible pop-in. Depending on your :abbr:`HLOD
  141. (Hierarchical Level of Detail)` setup, you may want to try both the **Self** and
  142. **Dependencies** :ref:`fade modes <doc_visibility_ranges_fade_mode>`.
  143. .. note::
  144. Nodes hidden via the **Visible** property are essentially removed from the
  145. visibility dependency tree, so dependent instances will not take the hidden
  146. node or its ancestors into account.
  147. In practice, this means that if the target of the **Visibility Parent** node
  148. is hidden by setting its **Visible** property to ``false``, the node will
  149. not be hidden according to the **Visibility Range Begin** value specified in
  150. the visibility parent.
  151. Configuration tips
  152. ------------------
  153. Use simpler materials at a distance to improve performance
  154. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  155. One way to further improve performance is to use simpler materials for distant
  156. LOD meshes. While using LOD meshes will reduce the number of vertices that need
  157. to be rendered, the per-pixel shading load for materials remains identical.
  158. However, per-pixel shading load is regularly a bottleneck on the GPU in complex
  159. 3D scenes. One way to reduce this shading load on the GPU is to use simpler
  160. materials when they don't make much of a visual difference.
  161. Performance gains when doing so should be carefully measured, as
  162. increasing the number of *unique* materials in a scene has a performance cost on
  163. its own. Still, using simpler materials for distant LOD meshes can still result
  164. in a net performance gain as a result of the fewer per-pixel calculations
  165. required.
  166. For example, on the materials used by distant LOD meshes, you can disable
  167. expensive material features such as:
  168. - Normal Map (especially on mobile platforms)
  169. - Rim
  170. - Clearcoat
  171. - Anisotropy
  172. - Height
  173. - Subsurface Scattering
  174. - Back Lighting
  175. - Refraction
  176. - Proximity Fade
  177. Use dithering for LOD transitions
  178. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  179. Godot currently only supports alpha-based fading for visibility ranges. You can
  180. however use dithering instead by using several different materials for different
  181. LOD levels.
  182. There are two advantages to using dithering over alpha blending for LOD transitions:
  183. - Higher performance, as dithering transparency is faster to render compared to
  184. alpha blending.
  185. - No visual glitches due to
  186. :ref:`transparency sorting issues <doc_3d_rendering_limitations_transparency_sorting>`
  187. during LOD transitions.
  188. The downside of dithering is that a "noisy" pattern is visible during LOD fade
  189. transitions. This may not be as noticeable at higher viewport resolutions or
  190. when temporal antialiasing is enabled.
  191. Also, as distance fade in BaseMaterial3D only supports fading up close *or*
  192. fading when far away, this setup is best used with only two LODs as part of the
  193. setup.
  194. - Ensure **Begin Margin** and **End Margin** is set to ``0.0`` on both
  195. MeshInstance3D nodes, as hysteresis or alpha fade are not desired here.
  196. - On both MeshInstance3D nodes, *decrease* **Begin** by the desired fade transition
  197. distance and *increase* **End** by the same distance. This is required for the
  198. dithering transition to actually be visible.
  199. - On the MeshInstance3D that is displayed up close, edit its material in the inspector.
  200. Set its **Distance Fade** mode to **Object Dither**. Set **Min Distance** to
  201. the same value as the visibility range **End**. Set **Max Distance** to the
  202. same value *minus* the fade transition distance.
  203. - On the MeshInstance3D that is displayed far away, edit its material in the inspector.
  204. Set its **Distance Fade** mode to **Object Dither**. Set **Min Distance** to
  205. the same value as the visibility range **Begin**. Set **Max Distance** to the
  206. same value *plus* the fade transition distance.