TerrainWorldRendererComponent.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Components/TerrainWorldRendererComponent.h>
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzCore/RTTI/BehaviorContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/Serialization/SerializeContext.h>
  13. #include <AzFramework/Entity/GameEntityContextBus.h>
  14. #include <Atom/RPI.Public/Scene.h>
  15. #include <Atom/RPI.Public/FeatureProcessorFactory.h>
  16. #include <TerrainRenderer/TerrainFeatureProcessor.h>
  17. namespace Terrain
  18. {
  19. void TerrainWorldRendererConfig::Reflect(AZ::ReflectContext* context)
  20. {
  21. Terrain::TerrainFeatureProcessor::Reflect(context);
  22. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  23. if (serialize)
  24. {
  25. serialize->Class<MeshConfiguration>()
  26. ->Version(2)
  27. ->Field("RenderDistance", &MeshConfiguration::m_renderDistance)
  28. ->Field("FirstLodDistance", &MeshConfiguration::m_firstLodDistance)
  29. ->Field("ClodEnabled", &MeshConfiguration::m_clodEnabled)
  30. ->Field("ClodDistance", &MeshConfiguration::m_clodDistance)
  31. ;
  32. serialize->Class<DetailMaterialConfiguration>()
  33. ->Version(1)
  34. ->Field("UseHeightBasedBlending", &DetailMaterialConfiguration::m_useHeightBasedBlending)
  35. ->Field("RenderDistance", &DetailMaterialConfiguration::m_renderDistance)
  36. ->Field("FadeDistance", &DetailMaterialConfiguration::m_fadeDistance)
  37. ->Field("Scale", &DetailMaterialConfiguration::m_scale)
  38. ;
  39. serialize->Class<ClipmapConfiguration>()
  40. ->Version(2)
  41. ->Field("ClipmapEnabled", &ClipmapConfiguration::m_clipmapEnabled)
  42. ->Field("ClipmapSize", &ClipmapConfiguration::m_clipmapSize)
  43. ->Field("MacroClipmapMaxResolution", &ClipmapConfiguration::m_macroClipmapMaxResolution)
  44. ->Field("DetailClipmapMaxResolution", &ClipmapConfiguration::m_detailClipmapMaxResolution)
  45. ->Field("MacroClipmapScaleBase", &ClipmapConfiguration::m_macroClipmapScaleBase)
  46. ->Field("DetailClipmapScaleBase", &ClipmapConfiguration::m_detailClipmapScaleBase)
  47. ->Field("MacroClipmapMarginSize", &ClipmapConfiguration::m_macroClipmapMarginSize)
  48. ->Field("DetailClipmapMarginSize", &ClipmapConfiguration::m_detailClipmapMarginSize)
  49. ;
  50. serialize->Class<TerrainWorldRendererConfig, AZ::ComponentConfig>()
  51. ->Version(3)
  52. ->Field("MeshConfiguration", &TerrainWorldRendererConfig::m_meshConfig)
  53. ->Field("DetailMaterialConfiguration", &TerrainWorldRendererConfig::m_detailMaterialConfig)
  54. ->Field("ClipmapConfiguration", &TerrainWorldRendererConfig::m_clipmapConfig)
  55. ;
  56. AZ::EditContext* editContext = serialize->GetEditContext();
  57. if (editContext)
  58. {
  59. editContext->Class<MeshConfiguration>("Mesh", "Settings related to rendering terrain meshes")
  60. ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshConfiguration::m_renderDistance, "Mesh render distance", "The distance from the camera that terrain meshes will render.")
  61. ->Attribute(AZ::Edit::Attributes::Min, 1.0f)
  62. ->Attribute(AZ::Edit::Attributes::SoftMin, 100.0f)
  63. ->Attribute(AZ::Edit::Attributes::Max, 100000.0f)
  64. ->Attribute(AZ::Edit::Attributes::SoftMax, 10000.0f)
  65. ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshConfiguration::m_firstLodDistance, "First LOD distance", "The distance from the camera that the first Lod renders to. Subsequent LODs will be at double the distance from the previous LOD.")
  66. ->Attribute(AZ::Edit::Attributes::Min, 1.0f)
  67. ->Attribute(AZ::Edit::Attributes::SoftMin, 10.0f)
  68. ->Attribute(AZ::Edit::Attributes::Max, 10000.0f)
  69. ->Attribute(AZ::Edit::Attributes::SoftMax, 1000.0f)
  70. ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshConfiguration::m_clodEnabled, "Continuous LOD (CLOD)", "Enables the use of continuous level of detail, which smoothly blends geometry between terrain lods.")
  71. ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshConfiguration::m_clodDistance, "CLOD Distance", "Distance in meters over which the first lod will blend into the next lod. Subsequent lod blend distances will double with each lod for a consistent visual appearance.")
  72. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  73. ->Attribute(AZ::Edit::Attributes::Max, 1000.0f)
  74. ->Attribute(AZ::Edit::Attributes::SoftMax, 100.0f)
  75. ->Attribute(AZ::Edit::Attributes::ReadOnly, &MeshConfiguration::IsClodDisabled)
  76. ;
  77. editContext->Class<DetailMaterialConfiguration>("Detail material", "Settings related to rendering detail surface materials.")
  78. ->DataElement(AZ::Edit::UIHandlers::CheckBox, &DetailMaterialConfiguration::m_useHeightBasedBlending, "Height based texture blending", "When turned on, detail materials will use the height texture to aid with blending.")
  79. ->DataElement(AZ::Edit::UIHandlers::Slider, &DetailMaterialConfiguration::m_renderDistance, "Detail material render distance", "The distance from the camera that the detail material will render.")
  80. ->Attribute(AZ::Edit::Attributes::Min, 1.0f)
  81. ->Attribute(AZ::Edit::Attributes::Max, 2048.0f)
  82. ->DataElement(AZ::Edit::UIHandlers::Slider, &DetailMaterialConfiguration::m_fadeDistance, "Detail material fade distance", "The distance over which the detail material will fade out into the macro material.")
  83. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  84. ->Attribute(AZ::Edit::Attributes::Max, 2048.0f)
  85. ->DataElement(AZ::Edit::UIHandlers::Slider, &DetailMaterialConfiguration::m_scale, "Detail material scale", "The scale at which all detail materials are rendered at.")
  86. ->Attribute(AZ::Edit::Attributes::SoftMin, 0.1f)
  87. ->Attribute(AZ::Edit::Attributes::Min, 0.0001f)
  88. ->Attribute(AZ::Edit::Attributes::SoftMax, 10.0f)
  89. ->Attribute(AZ::Edit::Attributes::Max, 10000.0f)
  90. ;
  91. editContext->Class<ClipmapConfiguration>("Clipmap", "Settings related to clipmap rendering")
  92. ->GroupElementToggle("Clipmap Enabled", &ClipmapConfiguration::m_clipmapEnabled)
  93. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  94. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  95. ->DataElement(AZ::Edit::UIHandlers::ComboBox, &ClipmapConfiguration::m_clipmapSize,
  96. "Clipmap image size",
  97. "The size of the clipmap image in each layer.")
  98. ->EnumAttribute(ClipmapConfiguration::ClipmapSize2048, "2048")
  99. ->EnumAttribute(ClipmapConfiguration::ClipmapSize1024, "1024")
  100. ->EnumAttribute(ClipmapConfiguration::ClipmapSize512, "512")
  101. ->DataElement(AZ::Edit::UIHandlers::Slider, &ClipmapConfiguration::m_macroClipmapMaxResolution,
  102. "Macro clipmap max resolution: texels/m",
  103. "The resolution of the highest resolution clipmap in the stack.")
  104. ->Attribute(AZ::Edit::Attributes::Min, 0.1f)
  105. ->Attribute(AZ::Edit::Attributes::SoftMin, 2.0f)
  106. ->Attribute(AZ::Edit::Attributes::SoftMax, 10.0f)
  107. ->Attribute(AZ::Edit::Attributes::Max, 100.0f)
  108. ->DataElement(AZ::Edit::UIHandlers::Slider, &ClipmapConfiguration::m_detailClipmapMaxResolution,
  109. "Detail clipmap max resolution: texels/m",
  110. "The resolution of the highest resolution clipmap in the stack.")
  111. ->Attribute(AZ::Edit::Attributes::Min, 10.0f)
  112. ->Attribute(AZ::Edit::Attributes::SoftMin, 512.0f)
  113. ->Attribute(AZ::Edit::Attributes::SoftMax, 2048.0f)
  114. ->Attribute(AZ::Edit::Attributes::Max, 4096.0f)
  115. ->DataElement(AZ::Edit::UIHandlers::Slider, &ClipmapConfiguration::m_macroClipmapScaleBase,
  116. "Macro clipmap scale base",
  117. "The scale base between two adjacent clipmap layers. \n"
  118. "For example, 3 means the (n+1)th clipmap covers 3^2 = 9 times the area covered by the nth clipmap.")
  119. ->Attribute(AZ::Edit::Attributes::Min, 1.1f)
  120. ->Attribute(AZ::Edit::Attributes::SoftMin, 2.0f)
  121. ->Attribute(AZ::Edit::Attributes::SoftMax, 4.0f)
  122. ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
  123. ->DataElement(AZ::Edit::UIHandlers::Slider, &ClipmapConfiguration::m_detailClipmapScaleBase,
  124. "Detail clipmap scale base",
  125. "The scale base between two adjacent clipmap layers. \n"
  126. "For example, 3 means the (n+1)th clipmap covers 3^2 = 9 times the area covered by the nth clipmap.")
  127. ->Attribute(AZ::Edit::Attributes::Min, 1.1f)
  128. ->Attribute(AZ::Edit::Attributes::SoftMin, 2.0f)
  129. ->Attribute(AZ::Edit::Attributes::SoftMax, 4.0f)
  130. ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
  131. ->DataElement(AZ::Edit::UIHandlers::Slider, &ClipmapConfiguration::m_macroClipmapMarginSize,
  132. "Macro clipmap margin size: texels",
  133. "The margin of the clipmap beyond the visible data. Increasing the margins results in less frequent clipmap updates "
  134. "but also results in lower resolution clipmaps rendering closer to the camera.")
  135. ->Attribute(AZ::Edit::Attributes::Min, 1u)
  136. ->Attribute(AZ::Edit::Attributes::SoftMin, 1u)
  137. ->Attribute(AZ::Edit::Attributes::SoftMax, 8u)
  138. ->Attribute(AZ::Edit::Attributes::Max, 16u)
  139. ->DataElement(AZ::Edit::UIHandlers::Slider, &ClipmapConfiguration::m_detailClipmapMarginSize,
  140. "Detail clipmap margin size: texels",
  141. "The margin of the clipmap beyond the visible data. Increasing the margins results in less frequent clipmap updates "
  142. "but also results in lower resolution clipmaps rendering closer to the camera.")
  143. ->Attribute(AZ::Edit::Attributes::Min, 1u)
  144. ->Attribute(AZ::Edit::Attributes::SoftMin, 1u)
  145. ->Attribute(AZ::Edit::Attributes::SoftMax, 8u)
  146. ->Attribute(AZ::Edit::Attributes::Max, 16u)
  147. // Note: m_extendedClipmapMarginSize, m_clipmapBlendSize won't be exposed because algorithm may change and we may not need them.
  148. ;
  149. editContext->Class<TerrainWorldRendererConfig>("Terrain World Renderer Component", "Enables terrain rendering")
  150. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  151. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("Level") }))
  152. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  153. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  154. ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldRendererConfig::m_meshConfig, "Mesh configuration", "")
  155. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  156. ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldRendererConfig::m_detailMaterialConfig, "Detail material configuration", "")
  157. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  158. ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldRendererConfig::m_clipmapConfig, "Clipmap configuration", "")
  159. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  160. ;
  161. }
  162. }
  163. }
  164. void TerrainWorldRendererComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  165. {
  166. services.push_back(AZ_CRC_CE("TerrainRendererService"));
  167. }
  168. void TerrainWorldRendererComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  169. {
  170. services.push_back(AZ_CRC_CE("TerrainRendererService"));
  171. }
  172. void TerrainWorldRendererComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  173. {
  174. services.push_back(AZ_CRC_CE("TerrainService"));
  175. }
  176. void TerrainWorldRendererComponent::Reflect(AZ::ReflectContext* context)
  177. {
  178. TerrainWorldRendererConfig::Reflect(context);
  179. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  180. if (serialize)
  181. {
  182. serialize->Class<TerrainWorldRendererComponent, AZ::Component>()->Version(0)->Field(
  183. "Configuration", &TerrainWorldRendererComponent::m_configuration);
  184. }
  185. }
  186. TerrainWorldRendererComponent::TerrainWorldRendererComponent(const TerrainWorldRendererConfig& configuration)
  187. : m_configuration(configuration)
  188. {
  189. }
  190. TerrainWorldRendererComponent::~TerrainWorldRendererComponent()
  191. {
  192. if (m_terrainRendererActive)
  193. {
  194. Deactivate();
  195. }
  196. }
  197. AZ::RPI::Scene* TerrainWorldRendererComponent::GetScene() const
  198. {
  199. // Find the entity context for the entity ID.
  200. AzFramework::EntityContextId entityContextId = AzFramework::EntityContextId::CreateNull();
  201. AzFramework::EntityIdContextQueryBus::EventResult(
  202. entityContextId, GetEntityId(), &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId);
  203. return AZ::RPI::Scene::GetSceneForEntityContextId(entityContextId);
  204. }
  205. void TerrainWorldRendererComponent::Activate()
  206. {
  207. // On component activation, register the terrain feature processor with Atom and the scene related to this entity context.
  208. if (AZ::RPI::Scene* scene = GetScene(); scene)
  209. {
  210. m_terrainFeatureProcessor = scene->EnableFeatureProcessor<Terrain::TerrainFeatureProcessor>();
  211. // Connect duplicate settings
  212. m_configuration.m_clipmapConfig.m_macroClipmapMaxRenderRadius = m_configuration.m_meshConfig.m_renderDistance;
  213. m_configuration.m_clipmapConfig.m_detailClipmapMaxRenderRadius = m_configuration.m_detailMaterialConfig.m_renderDistance;
  214. m_terrainFeatureProcessor->SetDetailMaterialConfiguration(m_configuration.m_detailMaterialConfig);
  215. m_terrainFeatureProcessor->SetMeshConfiguration(m_configuration.m_meshConfig);
  216. m_terrainFeatureProcessor->SetClipmapConfiguration(m_configuration.m_clipmapConfig);
  217. }
  218. m_terrainRendererActive = true;
  219. }
  220. void TerrainWorldRendererComponent::Deactivate()
  221. {
  222. // On component deactivation, unregister the feature processor and remove it from the default scene.
  223. m_terrainRendererActive = false;
  224. if (AZ::RPI::Scene* scene = GetScene(); scene)
  225. {
  226. if (scene->GetFeatureProcessor<Terrain::TerrainFeatureProcessor>())
  227. {
  228. scene->DisableFeatureProcessor<Terrain::TerrainFeatureProcessor>();
  229. }
  230. }
  231. m_terrainFeatureProcessor = nullptr;
  232. }
  233. bool TerrainWorldRendererComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
  234. {
  235. if (auto config = azrtti_cast<const TerrainWorldRendererConfig*>(baseConfig))
  236. {
  237. m_configuration = *config;
  238. return true;
  239. }
  240. return false;
  241. }
  242. bool TerrainWorldRendererComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
  243. {
  244. if (auto config = azrtti_cast<TerrainWorldRendererConfig*>(outBaseConfig))
  245. {
  246. *config = m_configuration;
  247. return true;
  248. }
  249. return false;
  250. }
  251. }