HairRenderObject.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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/Vector3.h>
  11. #include <Atom/RHI/DeviceBufferView.h>
  12. #include <Atom/RHI/DrawPacketBuilder.h>
  13. #include <Atom/RHI/GeometryView.h>
  14. // Hair specific
  15. #include <TressFX/AMD_TressFX.h>
  16. #include <TressFX/AMD_Types.h>
  17. #include <TressFX/TressFXConstantBuffers.h>
  18. #include <Rendering/HairCommon.h>
  19. #include <Rendering/SharedBuffer.h>
  20. #include <Rendering/HairDispatchItem.h>
  21. #include <Rendering/HairBuffersSemantics.h>
  22. #define TRESSFX_MIN_VERTS_PER_STRAND_FOR_GPU_ITERATION 64
  23. namespace AMD
  24. {
  25. struct float4x4;
  26. class TressFXAsset;
  27. class TressFXRenderingSettings;
  28. class TressFXSimulationSettings;
  29. }
  30. namespace AZ
  31. {
  32. namespace RHI
  33. {
  34. class DrawPacket;
  35. }
  36. namespace RPI
  37. {
  38. class Model;
  39. class Scene;
  40. class Shader;
  41. }
  42. namespace Render
  43. {
  44. namespace Hair
  45. {
  46. class HairFeatureProcessor;
  47. //! TressFXStrandLevelData represents blended bone data per hair strand that once calculated
  48. //! is passed between the skinning pass and the simulation shape constraints pass
  49. struct TressFXStrandLevelData
  50. {
  51. AMD::float4 skinningQuat;
  52. AMD::float4 vspQuat;
  53. AMD::float4 vspTranslation;
  54. };
  55. //!-----------------------------------------------------------------------------------------
  56. //!
  57. //! DynamicHairData
  58. //!
  59. //!-----------------------------------------------------------------------------------------
  60. //! Contains the writable data that is passed and used by 3 modules:
  61. //! simulation, signed distance field (collisions), and rendering.
  62. //! Rendering uses current position and tangent as SRVs in VS for computing creation and skinning.
  63. //! Since this data is per object (hence per object dispatch) and requires sync point (barrier) between the
  64. //! the passes, a single buffer is allocated and is shared by all hair objects and their 'streams'
  65. //! where each have buffer view so that it points to its own portion of the original buffer's data.
  66. //! The shared buffer is therefore declared in the pass Srg to result in an execution dependency
  67. //! so that a barrier will be created. It also represents less overhead since we are using a single
  68. //! coordinated / shared buffer sync point rather than many barriers (per object per buffer).
  69. //!-----------------------------------------------------------------------------------------
  70. class DynamicHairData
  71. {
  72. friend class HairRenderObject;
  73. public:
  74. //! Creates the GPU dynamic buffers of a single hair object
  75. //! Equivalent to TressFXDynamicHairData::CreateGPUResources
  76. bool CreateDynamicGPUResources(
  77. Data::Instance<RPI::Shader> computeShader,
  78. Data::Instance<RPI::Shader> rasterShader,
  79. uint32_t vertexCount, uint32_t strandsCount);
  80. //! Data upload - copy the hair mesh asset data (positions and tangents) into the buffers.
  81. //! In the following line I assume that positions and tangents are of the same size.
  82. //! Equivalent to: TressFXDynamicHairData::UploadGPUData
  83. bool UploadGPUData(const char* name, void* positions, void* tangents);
  84. //! Preparation of the descriptors table of all the dynamic stream buffers within the class.
  85. //! Do not call this method before calling CreateAndBindGPUResources as it is already called
  86. //! from CreateAndBindGPUResources.
  87. //! This method can be called also for retrieving the descriptors table (SharedBuffer)
  88. static void PrepareSrgDescriptors(
  89. AZStd::vector<SrgBufferDescriptor>& descriptorArray,
  90. int32_t vertexCount, uint32_t strandsCount);
  91. void PrepareSrgDescriptors(int32_t vertexCount, uint32_t strandsCount)
  92. {
  93. PrepareSrgDescriptors(m_dynamicBuffersDescriptors, vertexCount, strandsCount);
  94. }
  95. Data::Instance<RPI::ShaderResourceGroup> GetSimSrgForCompute()
  96. {
  97. return m_initialized ? m_simSrgForCompute : nullptr;
  98. }
  99. Data::Instance<RPI::ShaderResourceGroup> GetSimSrgForRaster()
  100. {
  101. return m_initialized ? m_simSrgForRaster : nullptr; }
  102. bool IsInitialized() { return m_initialized; }
  103. private:
  104. //! Matching between the buffers Srg and its buffers descriptors, this method fills the Srg with
  105. //! the views of the buffers to be used by the hair instance.
  106. bool BindPerObjectSrgForCompute();
  107. bool BindPerObjectSrgForRaster();
  108. //! The descriptors required to allocate and associate the dynamic buffers with the SRGs
  109. //! Each descriptor also contains the byte offsets of the sub-buffers in the global dynamic
  110. //! array for the data copy.
  111. AZStd::vector<SrgBufferDescriptor> m_dynamicBuffersDescriptors;
  112. //! The following dynamic buffer views are views 'sub-buffers' located within a global large
  113. //! dynamic buffer exposed and connected as an attachment between the passes and therefore
  114. //! creates both dependency order between passes execution and sync point barrier.
  115. //! This indirectly forces the sync to be applied to all 'sub-buffers' used by each of the
  116. //! HairObjects / HairDispatches and therefore allows us to change their data in the shader
  117. //! between passes.
  118. AZStd::vector<Data::Instance<RHI::BufferView>> m_dynamicBuffersViews; // RW used for the Compute
  119. AZStd::vector<Data::Instance<RHI::BufferView>> m_readBuffersViews; // Read only used for the Raster fill
  120. //! The following vector is required in order to keep the allocators 'alive' or
  121. //! else they are cleared from the buffer via the reference mechanism.
  122. AZStd::vector<Data::Instance<HairSharedBufferAllocation>> m_dynamicViewAllocators;
  123. //------------------------------------------------------------------
  124. //! The following SRGs are the ones represented by this class' data.
  125. //! These Srgs are required for the changed dynamic data passed between the
  126. //! skinning, simulation and rendering passes / shaders.
  127. //! It is the TressFX equivalent of the set:
  128. //! - pSimPosTanLayout / m_pSimBindSets
  129. //------------------------------------------------------------------
  130. Data::Instance<RPI::ShaderResourceGroup> m_simSrgForCompute; //! TressFX equivalent: pSimPosTanLayout / m_pSimBindSets
  131. Data::Instance<RPI::ShaderResourceGroup> m_simSrgForRaster; //! Targeting only the Fill pass / shader
  132. bool m_initialized = false;
  133. };
  134. //!-----------------------------------------------------------------------------------------
  135. //!
  136. //! HairRenderObject
  137. //!
  138. //!-----------------------------------------------------------------------------------------
  139. //! This class is equivalent to TressFXHairObject and HairStrands (the later is mainly a wrapper).
  140. //! This is the class that holds all the raw data used by all the hair passes and shaders.
  141. //!-----------------------------------------------------------------------------------------
  142. class HairRenderObject final
  143. : public Data::InstanceData
  144. {
  145. friend HairFeatureProcessor;
  146. public:
  147. AZ_RTTI(HairRenderObject, "{58F48A58-C5B9-4CAE-9AFD-9B3AF3A01C73}");
  148. HairRenderObject() = default;
  149. ~HairRenderObject();
  150. void Release();
  151. bool Init(
  152. HairFeatureProcessor* featureProcessor, const char* assetName, AMD::TressFXAsset* asset,
  153. AMD::TressFXSimulationSettings* simSettings, AMD::TressFXRenderingSettings* renderSettings
  154. );
  155. bool BuildDrawPacket(RPI::Shader* geometryShader, RHI::DrawPacketBuilder::DrawRequest& drawRequest);
  156. const RHI::DrawPacket* GetGeometrylDrawPacket(RPI::Shader* geometryShader);
  157. //! Creates and fill the dispatch item associated with the compute shader
  158. bool BuildDispatchItem(RPI::Shader* computeShader, DispatchLevel dispatchLevel);
  159. const RHI::DispatchItem* GetDispatchItem(RPI::Shader* computeShader);
  160. void PrepareHairGenerationSrgDescriptors(uint32_t vertexCount, uint32_t numStrands);
  161. // Based on SkinnedMeshInputLod::CreateStaticBuffer
  162. bool CreateAndBindHairGenerationBuffers(uint32_t vertexCount, uint32_t strandsCount);
  163. //! Updates the buffers data for the hair generation.
  164. //! Does NOT update the bone matrices - they will be updated every frame.
  165. bool UploadGPUData(const char* name, AMD::TressFXAsset* asset);
  166. Data::Instance<RPI::ShaderResourceGroup> GetHairGenerationSrg()
  167. {
  168. return m_hairGenerationSrg;
  169. }
  170. bool BindPerObjectSrgForCompute()
  171. {
  172. return m_dynamicHairData.IsInitialized() ? m_dynamicHairData.BindPerObjectSrgForCompute() : false;
  173. }
  174. bool BindPerObjectSrgForRaster()
  175. {
  176. return m_dynamicHairData.IsInitialized() ? m_dynamicHairData.BindPerObjectSrgForRaster() : false;
  177. }
  178. //!-----------------------------------------------------------------
  179. //! Methods partially imported from TressFXHairObject
  180. //!-----------------------------------------------------------------
  181. int GetNumTotalHairVertices() const { return m_NumTotalVertices; }
  182. int GetNumTotalHairStrands() const { return m_NumTotalStrands; }
  183. int GetNumVerticesPerStrand() const { return m_NumVerticesPerStrand; }
  184. int GetCPULocalShapeIterations() const { return m_CPULocalShapeIterations; }
  185. int GetNumFollowHairsPerGuideHair() const { return m_NumFollowHairsPerGuideHair; }
  186. int GetNumGuideHairs() const
  187. {
  188. return GetNumTotalHairStrands() / (GetNumFollowHairsPerGuideHair() + 1);
  189. }
  190. //! This method is mainly a wrapper around BindRenderSrgResources to keep the
  191. //! connection in code to the TressFX method.
  192. //! Bind Render Srg (m_hairRenderSrg) resources. No resources data update should be doe here
  193. //! Notice that this also loads the images and is slower if a new asset is required.
  194. //! If the image was not changed it should only bind without the retrieve operation.
  195. bool PopulateDrawStrandsBindSet(AMD::TressFXRenderingSettings* pRenderSettings/*=nullptr*/);
  196. // This function will be called when the image asset changed for the component.
  197. bool LoadImageAsset(AMD::TressFXRenderingSettings* pRenderSettings);
  198. bool UploadRenderingGPUResources(AMD::TressFXAsset& asset);
  199. //! Creation of the render Srg m_hairRenderSrg, followed by creation and binding of the
  200. //! GPU render resources: vertex thickness, vertex UV, hair albedo maps and two constant buffers.
  201. bool CreateRenderingGPUResources(
  202. Data::Instance<RPI::Shader> shader, AMD::TressFXAsset& asset, const char* assetName);
  203. bool Update();
  204. //! This method needs to be called in order to fill the bone matrices before the skinning
  205. void UpdateBoneMatrices(const AMD::float4x4* pBoneMatricesInWS, int numBoneMatrices);
  206. //! update of the skinning matrices per frame. The matrices are in model / local space
  207. //! which is why the entity world matrix is also passed.
  208. void UpdateBoneMatrices(const AZ::Matrix3x4& entityWorldMatrix, const AZStd::vector<AZ::Matrix3x4>& boneMatrices);
  209. void InitBoneMatricesPlaceHolder(int numBoneMatrices);
  210. void SetFrameDeltaTime(float deltaTime);
  211. //! Updating the bone matrices for the skinning in the simulation constant buffer.
  212. //! pBoneMatricesInWS constraints array of column major bone matrices in world space.
  213. void UpdateRenderingParameters(
  214. const AMD::TressFXRenderingSettings* parameters, const int nodePoolSize,
  215. float distance, bool shadowUpdate /*= false*/);
  216. AMD::TressFXRenderParams* GetHairRenderParams() { return m_renderCB.get(); };
  217. //! Update of simulation constant buffer.
  218. //! Notice that the bone matrices are set elsewhere and should be updated before GPU submit.
  219. void UpdateSimulationParameters(const AMD::TressFXSimulationSettings* settings, float timeStep);
  220. void SetWind(const Vector3& windDir, float windMag, int frame);
  221. void SetRenderIndex(uint32_t renderIndex) { m_RenderIndex = renderIndex; }
  222. void ResetPositions() { m_simCB->g_ResetPositions = 1.0f; }
  223. void IncreaseSimulationFrame()
  224. {
  225. m_simCB->g_ResetPositions = (m_SimulationFrame < 2) ? 1.0f : 0.0f;
  226. m_SimulationFrame++;
  227. }
  228. bool IsEnabled()
  229. {
  230. return m_enabled;
  231. }
  232. void SetEnabled(bool enable)
  233. {
  234. m_enabled = enable;
  235. }
  236. //!-----------------------------------------------------------------
  237. private:
  238. //----------------------- Private Methods --------------------------
  239. bool BindRenderSrgResources();
  240. void PrepareRenderSrgDescriptors();
  241. bool GetShaders();
  242. //------------------------------ Data ------------------------------
  243. static uint32_t s_objectCounter;
  244. //! The feature processor is the centralized class that gathers all render nodes and
  245. //! responsible for the various stages and passes' updates
  246. HairFeatureProcessor* m_featureProcessor = nullptr;
  247. //! Skinning compute shader used for creation of the compute Srgs and dispatch item
  248. Data::Instance<RPI::Shader> m_skinningShader = nullptr;
  249. //! Compute dispatch items map per the existing passes
  250. AZStd::unordered_map<RPI::Shader*, Data::Instance<HairDispatchItem>> m_dispatchItems;
  251. //! Geometry raster shader used for creation of the raster Srgs.
  252. //! Since the Srgs for geometry raster are the same across the shaders we keep
  253. //! only a single shader - if this to change in the future, several shaders and sets
  254. //! of dynamic Srgs should be created.
  255. Data::Instance<RPI::Shader> m_geometryRasterShader = nullptr;
  256. //! DrawPacket for the multi object geometry raster pass.
  257. AZStd::unordered_map<RPI::Shader*, RHI::ConstPtr<RHI::DrawPacket>> m_geometryDrawPackets;
  258. float m_frameDeltaTime = 0.02;
  259. //! The following are the configuration settings that might be required during the update.
  260. AMD::TressFXSimulationSettings* m_simSettings = nullptr;
  261. AMD::TressFXRenderingSettings* m_renderSettings = nullptr;
  262. //! Hair asset information
  263. uint32_t m_TotalIndices = 0;
  264. uint32_t m_NumTotalVertices = 0;
  265. uint32_t m_numGuideVertices = 0;
  266. uint32_t m_NumTotalStrands = 0;
  267. uint32_t m_NumVerticesPerStrand = 0;
  268. uint32_t m_CPULocalShapeIterations = 0;
  269. uint32_t m_NumFollowHairsPerGuideHair = 0;
  270. // LOD calculations factor
  271. float m_LODHairDensity = 1.0f;
  272. bool m_enabled = true;
  273. //! Controls reset / copy base hair state
  274. uint32_t m_SimulationFrame = 0;
  275. //! The index used as a look up into the material array during the resolve pass
  276. uint32_t m_RenderIndex = 0;
  277. //!-----------------------------------------------------------------
  278. //! The hair dynamic per instance buffers such as vertices, tangents, etc..
  279. //! The data of these buffers is read/write and will change between passes.
  280. DynamicHairData m_dynamicHairData;
  281. //!-----------------------------------------------------------------
  282. //! Static buffers & Srg: Initial position, bones transform skinning
  283. //! data, physical hair properties..
  284. //!-----------------------------------------------------------------
  285. AZStd::vector<Data::Instance<RPI::Buffer>> m_hairGenerationBuffers;
  286. AZStd::vector<SrgBufferDescriptor> m_hairGenerationDescriptors;
  287. //! The simulation parameters constant buffer.
  288. HairUniformBuffer<AMD::TressFXSimulationParams> m_simCB;
  289. Data::Instance<RPI::ShaderResourceGroup> m_hairGenerationSrg;
  290. //!-----------------------------------------------------------------
  291. //! TressFXRenderParams Srg buffers and declarations
  292. //! The rendering buffers and structures required for the render draw
  293. //! calls and are sent to the GPU using TressFXRenderParams Srg.
  294. //!-----------------------------------------------------------------
  295. //! Vertex and UV buffers.
  296. //! Naming was not changed to preserve correlation to TressFXHairObject.h
  297. Data::Instance<RPI::Buffer> m_hairVertexRenderParams;
  298. Data::Instance<RPI::Buffer> m_hairTexCoords;
  299. //! Base color of the hair root and per strand texture.
  300. Data::Instance<RPI::Image> m_baseAlbedo;
  301. Data::Instance<RPI::Image> m_strandAlbedo;
  302. HairUniformBuffer<AMD::TressFXRenderParams> m_renderCB;
  303. HairUniformBuffer<AMD::TressFXStrandParams> m_strandCB;
  304. AZStd::vector<SrgBufferDescriptor> m_hairRenderDescriptors;
  305. // Equivalent to m_pRenderLayoutBindSet in TressFX.
  306. Data::Instance<RPI::ShaderResourceGroup> m_hairRenderSrg;
  307. //! Index buffer for the render pass via draw calls - naming was kept
  308. Data::Instance<RHI::Buffer> m_indexBuffer;
  309. RHI::GeometryView m_geometryView;
  310. //-------------------------------------------------------------------
  311. AZStd::mutex m_mutex;
  312. };
  313. } // namespace Hair
  314. } // namespace Render
  315. } // namespace AZ