TerrainMeshManager.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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. #pragma once
  9. #include <AzCore/base.h>
  10. #include <AzCore/Math/Aabb.h>
  11. #include <AzCore/Outcome/Outcome.h>
  12. #include <AzCore/std/containers/vector.h>
  13. #include <AtomCore/Instance/Instance.h>
  14. #include <AzFramework/Terrain/TerrainDataRequestBus.h>
  15. #include <Atom/RHI.Reflect/ShaderInputNameIndex.h>
  16. #include <Atom/RPI.Public/Shader/ShaderSystemInterface.h>
  17. #include <Atom/RPI.Public/FeatureProcessor.h>
  18. #include <Atom/RPI.Public/MeshDrawPacket.h>
  19. #include <Atom/Feature/RayTracing/RayTracingFeatureProcessorInterface.h>
  20. #include <TerrainRenderer/Vector2i.h>
  21. namespace AZ::RPI
  22. {
  23. class Scene;
  24. }
  25. namespace AZ::RHI
  26. {
  27. struct BufferViewDescriptor;
  28. }
  29. namespace Terrain
  30. {
  31. struct MeshConfiguration
  32. {
  33. AZ_CLASS_ALLOCATOR(MeshConfiguration, AZ::SystemAllocator);
  34. AZ_RTTI(MeshConfiguration, "{D94D831B-67C0-46C5-9707-AACD2716A2C0}");
  35. MeshConfiguration() = default;
  36. virtual ~MeshConfiguration() = default;
  37. float m_renderDistance = 4096.0f;
  38. float m_firstLodDistance = 128.0f;
  39. bool m_clodEnabled = true;
  40. float m_clodDistance = 16.0f;
  41. bool operator==(const MeshConfiguration& other) const
  42. {
  43. return m_renderDistance == other.m_renderDistance
  44. && m_firstLodDistance == other.m_firstLodDistance
  45. && m_clodEnabled == other.m_clodEnabled
  46. && m_clodDistance == other.m_clodDistance
  47. ;
  48. }
  49. bool CheckWouldRequireRebuild(const MeshConfiguration& other) const
  50. {
  51. return !(m_renderDistance == other.m_renderDistance
  52. && m_firstLodDistance == other.m_firstLodDistance
  53. && m_clodEnabled == other.m_clodEnabled
  54. );
  55. }
  56. bool operator!=(const MeshConfiguration& other) const
  57. {
  58. return !(other == *this);
  59. }
  60. bool IsClodDisabled() // Since the edit context attribute is "ReadOnly" instead of "Enabled", the logic needs to be reversed.
  61. {
  62. return !m_clodEnabled;
  63. }
  64. };
  65. class TerrainMeshManager
  66. : private AzFramework::Terrain::TerrainDataNotificationBus::Handler
  67. {
  68. private:
  69. using MaterialInstance = AZ::Data::Instance<AZ::RPI::Material>;
  70. public:
  71. AZ_RTTI(TerrainMeshManager, "{62C84AD8-05FE-4C78-8501-A2DB6731B9B7}");
  72. AZ_DISABLE_COPY_MOVE(TerrainMeshManager);
  73. TerrainMeshManager();
  74. ~TerrainMeshManager();
  75. void Initialize(AZ::RPI::Scene& parentScene);
  76. void SetConfiguration(const MeshConfiguration& config);
  77. bool IsInitialized() const;
  78. void Reset();
  79. void SetMaterial(MaterialInstance materialInstance);
  80. void Update(const AZ::RPI::ViewPtr mainView, AZ::Data::Instance<AZ::RPI::ShaderResourceGroup>& terrainSrg);
  81. void DrawMeshes(const AZ::RPI::FeatureProcessor::RenderPacket& process, const AZ::RPI::ViewPtr mainView);
  82. void SetRebuildDrawPackets();
  83. private:
  84. using HeightDataType = uint16_t;
  85. using NormalDataType = int8_t;
  86. using NormalXYDataType = AZStd::pair<NormalDataType, NormalDataType>;
  87. static constexpr AZ::RHI::Format XYPositionFormat = AZ::RHI::Format::R8G8_UNORM;
  88. static constexpr AZ::RHI::Format HeightFormat = AZ::RHI::Format::R16_UNORM;
  89. static constexpr AZ::RHI::Format NormalFormat = AZ::RHI::Format::R8G8_SNORM;
  90. static constexpr uint32_t RayTracingQuads1D = 200;
  91. static constexpr HeightDataType NoTerrainVertexHeight = AZStd::numeric_limits<HeightDataType>::max();
  92. enum StreamIndex : uint32_t
  93. {
  94. XYPositions,
  95. Heights,
  96. Normals,
  97. LodHeights,
  98. LodNormals,
  99. Count,
  100. };
  101. struct RtSector
  102. {
  103. // Ray tracing structures - Currently no data is shared due to ray tracing's format requirements, in the future this could
  104. // be de-duplicated with custom ray tracing shaders.
  105. AZ::Data::Instance<AZ::RPI::Buffer> m_positionsBuffer;
  106. AZ::Data::Instance<AZ::RPI::Buffer> m_normalsBuffer;
  107. struct MeshGroup
  108. {
  109. AZ::Uuid m_id { AZ::Uuid::CreateRandom() };
  110. AZ::Render::RayTracingFeatureProcessorInterface::Mesh m_mesh;
  111. AZ::Render::RayTracingFeatureProcessorInterface::SubMeshVector m_submeshVector;
  112. bool m_isVisible = false;
  113. };
  114. AZStd::array<MeshGroup, 5> m_meshGroups; // 0 is the primary, 1-4 are the quadrants.
  115. };
  116. struct Sector
  117. {
  118. AZ::RHI::GeometryView m_geometryView;
  119. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> m_srg;
  120. AZ::Aabb m_aabb = AZ::Aabb::CreateNull();
  121. AZStd::array<AZ::Aabb, 4> m_quadrantAabbs;
  122. Vector2i m_worldCoord = AZStd::numeric_limits<int32_t>::max();
  123. // When drawing, either the m_rhiDrawPacket will be used, or some number of the m_rhiDrawPacketQuadrants
  124. AZ::RHI::ConstPtr<AZ::RHI::DrawPacket> m_rhiDrawPacket;
  125. AZStd::array<AZ::RHI::ConstPtr<AZ::RHI::DrawPacket>, 4> m_rhiDrawPacketQuadrant;
  126. AZStd::array<AZ::RHI::GeometryView, 4> m_quadrantGeometryViews;
  127. AZ::Data::Instance<AZ::RPI::Buffer> m_heightsNormalsBuffer;
  128. AZ::Data::Instance<AZ::RPI::Buffer> m_lodHeightsNormalsBuffer;
  129. // Hold reference to the draw srgs so they don't get released.
  130. AZStd::fixed_vector<AZ::Data::Instance<AZ::RPI::ShaderResourceGroup>, AZ::RHI::DrawPacketBuilder::DrawItemCountMax> m_perDrawSrgs;
  131. AZStd::unique_ptr<RtSector> m_rtData;
  132. bool m_hasData = false;
  133. bool m_isQueuedForSrgCompile = false;
  134. };
  135. struct SectorLodGrid
  136. {
  137. AZStd::vector<Sector> m_sectors;
  138. // The world space sector coord of the top most left item
  139. Vector2i m_startCoord = AZStd::numeric_limits<int32_t>::max();
  140. };
  141. struct ShaderObjectData // Must align with struct in object srg
  142. {
  143. AZStd::array<float, 2> m_xyTranslation{ 0.0f, 0.0f };
  144. float m_xyScale{ 1.0f };
  145. uint32_t m_lodLevel{ 0 };
  146. float m_rcpLodLevel{ 1.0f };
  147. };
  148. struct alignas(16) ShaderMeshData
  149. {
  150. AZStd::array<float, 3> m_mainCameraPosition{ 0.0f, 0.0f, 0.0f };
  151. float m_firstLodDistance;
  152. float m_rcpClodDistance;
  153. float m_rcpGridSize;
  154. float m_gridToQuadScale;
  155. };
  156. struct SectorDataRequest
  157. {
  158. AZ::Vector2 m_worldStartPosition;
  159. float m_vertexSpacing;
  160. int16_t m_samplesX;
  161. int16_t m_samplesY;
  162. AzFramework::Terrain::TerrainDataRequests::Sampler m_samplerType =
  163. AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP;
  164. bool m_useVertexOrderRemap = false;
  165. };
  166. struct CachedDrawData
  167. {
  168. AZ::Data::Instance<AZ::RPI::Shader> m_shader;
  169. AZ::RPI::ShaderOptionGroup m_shaderOptions;
  170. const AZ::RHI::PipelineState* m_pipelineState;
  171. AZ::RHI::DrawListTag m_drawListTag;
  172. AZ::RHI::Ptr<AZ::RHI::ShaderResourceGroupLayout> m_drawSrgLayout;
  173. AZ::RPI::ShaderVariant m_shaderVariant;
  174. AZ::Name m_materialPipelineName;
  175. };
  176. struct HeightNormalVertex
  177. {
  178. HeightDataType m_height;
  179. NormalXYDataType m_normal;
  180. };
  181. struct CandidateSector
  182. {
  183. AZ::Aabb m_aabb;
  184. const AZ::RHI::DrawPacket* m_rhiDrawPacket;
  185. };
  186. struct XYPosition
  187. {
  188. uint8_t m_posx;
  189. uint8_t m_posy;
  190. };
  191. struct RayTracedItem
  192. {
  193. Sector* m_sector;
  194. uint32_t m_meshGroupIndex;
  195. uint32_t m_lodLevel;
  196. };
  197. // AzFramework::Terrain::TerrainDataNotificationBus overrides...
  198. void OnTerrainDataCreateEnd() override;
  199. void OnTerrainDataDestroyBegin() override;
  200. void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override;
  201. void ClearSectorBuffers();
  202. bool UpdateGridSize(float distanceToFirstLod);
  203. void BuildDrawPacket(Sector& sector);
  204. void BuildRtSector(Sector& sector, uint32_t lodLevel);
  205. void RebuildSectors();
  206. void RebuildDrawPackets();
  207. void RemoveRayTracedMeshes();
  208. AZ::RHI::StreamBufferView CreateStreamBufferView(AZ::Data::Instance<AZ::RPI::Buffer>& buffer, uint32_t offset = 0);
  209. void CreateCommonBuffers();
  210. void UpdateSectorBuffers(Sector& sector, const AZStd::span<const HeightNormalVertex> heightsNormals);
  211. void UpdateSectorLodBuffers(Sector& sector,
  212. const AZStd::span<const HeightNormalVertex> originalHeightsNormals,
  213. const AZStd::span<const HeightNormalVertex> lodHeightsNormals);
  214. void GatherMeshData(SectorDataRequest request, AZStd::vector<HeightNormalVertex>& meshHeightsNormals, AZ::Aabb& meshAabb, bool& terrainExistsAnywhere);
  215. void CheckLodGridsForUpdate(AZ::Vector3 newPosition);
  216. void ProcessSectorUpdates(AZStd::vector<AZStd::vector<Sector*>>& sectorUpdates);
  217. AZ::Data::Instance<AZ::RPI::Buffer> CreateMeshBufferInstance(
  218. uint32_t elementSize,
  219. uint32_t elementCount,
  220. const void* initialData = nullptr,
  221. const char* name = nullptr);
  222. AZ::Data::Instance<AZ::RPI::Buffer> CreateRayTracingMeshBufferInstance(
  223. AZ::RHI::Format elementFormat,
  224. uint32_t elementCount,
  225. const void* initialData = nullptr,
  226. const char* name = nullptr);
  227. void UpdateCandidateSectors();
  228. void CreateAabbQuadrants(const AZ::Aabb& aabb, AZStd::span<AZ::Aabb, 4> quadrantAabb);
  229. template<typename Callback>
  230. void ForOverlappingSectors(const AZ::Aabb& bounds, Callback callback);
  231. MeshConfiguration m_config;
  232. AZ::RPI::Scene* m_parentScene;
  233. AZ::Render::RayTracingFeatureProcessorInterface* m_rayTracingFeatureProcessor;
  234. MaterialInstance m_materialInstance;
  235. AZStd::vector<CachedDrawData> m_cachedDrawData; // Holds common parts of draw packets
  236. AZ::RPI::ShaderSystemInterface::GlobalShaderOptionUpdatedEvent::Handler m_handleGlobalShaderOptionUpdate;
  237. AZ::RHI::ShaderInputNameIndex m_srgMeshDataIndex = "m_meshData";
  238. AZ::RHI::ShaderInputNameIndex m_patchDataIndex = "m_patchData";
  239. AZ::Data::Instance<AZ::RPI::Buffer> m_xyPositionsBuffer;
  240. AZ::Data::Instance<AZ::RPI::Buffer> m_indexBuffer;
  241. AZ::Data::Instance<AZ::RPI::Buffer> m_rtIndexBuffer;
  242. AZ::Data::Instance<AZ::RPI::Buffer> m_dummyLodHeightsNormalsBuffer;
  243. AZ::RHI::IndexBufferView m_indexBufferView;
  244. AZStd::vector<SectorLodGrid> m_sectorLods;
  245. AZStd::vector<CandidateSector> m_candidateSectors;
  246. AZStd::vector<Sector*> m_sectorsThatNeedSrgCompiled;
  247. uint32_t m_1dSectorCount = 0;
  248. // Sector x/y positions used to make it easier to calculate x/y positions for ray tracing meshes. This is particularly
  249. // relevant because the positions may have been reordered for vertex cache efficiency.
  250. AZStd::vector<XYPosition> m_xyPositions;
  251. // Set up the initial camera position impossible to force an update.
  252. AZ::Vector3 m_cameraPosition = AZ::Vector3::CreateAxisX(AZStd::numeric_limits<float>::max());
  253. AzFramework::Terrain::FloatRange m_worldHeightBounds;
  254. float m_sampleSpacing = 1.0f;
  255. AZ::RPI::Material::ChangeId m_lastMaterialChangeId;
  256. AZStd::vector<uint16_t> m_vertexOrder; // Maps from regular linear order to actual vertex order positions
  257. // Tracks which sectors are currently in the ray tracing system so they can be easily compared and updated each frame.
  258. AZStd::vector<RayTracedItem> m_rayTracedItems;
  259. uint8_t m_gridSize = 0; // number of quads in a single row of a sector
  260. uint8_t m_gridVerts1D = 0; // number of vertices along sector edge (m_gridSize + 1)
  261. uint16_t m_gridVerts2D = 0; // number of vertices in sector
  262. bool m_isInitialized{ false };
  263. bool m_rebuildSectors{ true };
  264. bool m_rebuildDrawPackets{ false };
  265. bool m_rayTracingEnabled{ false };
  266. AZ::RHI::Handle<uint32_t> m_meshMovedFlag;
  267. };
  268. }