RootConstantsExampleComponent.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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 <RootConstantsExampleComponent.h>
  9. #include <SampleComponentManager.h>
  10. #include <SampleComponentConfig.h>
  11. #include <AzCore/Asset/AssetManagerBus.h>
  12. #include <AzCore/IO/FileIO.h>
  13. #include <AzFramework/Components/CameraBus.h>
  14. #include <AzFramework/Components/TransformComponent.h>
  15. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  16. #include <Atom/Feature/CoreLights/CoreLightsConstants.h>
  17. #include <Atom/RHI/DrawPacket.h>
  18. #include <Atom/RHI/DrawPacketBuilder.h>
  19. #include <Atom/RHI.Reflect/InputStreamLayoutBuilder.h>
  20. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  21. #include <Atom/RPI.Public/RPISystemInterface.h>
  22. #include <Atom/RPI.Public/Shader/Shader.h>
  23. #include <RHI/BasicRHIComponent.h>
  24. namespace AtomSampleViewer
  25. {
  26. using namespace AZ;
  27. void RootConstantsExampleComponent::Reflect(ReflectContext* context)
  28. {
  29. if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
  30. {
  31. serializeContext->Class < RootConstantsExampleComponent, Component>()
  32. ->Version(0)
  33. ;
  34. }
  35. }
  36. RootConstantsExampleComponent::RootConstantsExampleComponent()
  37. {
  38. }
  39. void RootConstantsExampleComponent::ResetCamera()
  40. {
  41. const float pitch = -AZ::Constants::QuarterPi / 2.0f;
  42. const float distance = 10.0f;
  43. AZ::Quaternion orientation = AZ::Quaternion::CreateRotationX(pitch);
  44. AZ::Vector3 position = orientation.TransformVector(AZ::Vector3(0, -distance, 0));
  45. AZ::TransformBus::Event(GetCameraEntityId(), &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateFromQuaternionAndTranslation(orientation, position));
  46. }
  47. void RootConstantsExampleComponent::PrepareRenderData()
  48. {
  49. // Init assembly data (vertex/index buffers and views)...
  50. {
  51. const char* modelsPath[] =
  52. {
  53. "objects/shaderball_simple.fbx.azmodel",
  54. "objects/bunny.fbx.azmodel",
  55. "testdata/objects/cube/cube.fbx.azmodel"
  56. };
  57. for (uint32_t i = 0; i < AZ_ARRAY_SIZE(modelsPath); ++i)
  58. {
  59. Data::AssetId modelAssetId;
  60. Data::AssetCatalogRequestBus::BroadcastResult(
  61. modelAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  62. modelsPath[i], azrtti_typeid<AZ::RPI::ModelAsset>(), false);
  63. if (!modelAssetId.IsValid())
  64. {
  65. return;
  66. }
  67. // Load the asset
  68. auto modelAsset = Data::AssetManager::Instance().GetAsset<AZ::RPI::ModelAsset>(
  69. modelAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
  70. modelAsset.BlockUntilLoadComplete();
  71. if (!modelAsset.IsReady())
  72. {
  73. return;
  74. }
  75. auto model = AZ::RPI::Model::FindOrCreate(modelAsset);
  76. AZ_Error("Render", model, "Failed to load model %s", modelsPath[i]);
  77. m_models.push_back(AZStd::move(model));
  78. }
  79. }
  80. // Load shader data...
  81. {
  82. RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor;
  83. const char* shaderFilepath = "Shaders/RootConstantsExample/ColorMesh.azshader";
  84. Data::Asset<RPI::ShaderAsset> shaderAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::ShaderAsset>(shaderFilepath, RPI::AssetUtils::TraceLevel::Error);
  85. Data::Instance<RPI::Shader> shader = RPI::Shader::FindOrCreate(shaderAsset);
  86. if (!shader)
  87. {
  88. AZ_Error("Render", false, "Failed to find or create shader instance from shader asset with path %s", shaderFilepath);
  89. return;
  90. }
  91. const RPI::ShaderVariant& shaderVariant = shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  92. shaderVariant.ConfigurePipelineState(pipelineStateDescriptor);
  93. m_drawListTag = shader->GetDrawListTag();
  94. m_scene->ConfigurePipelineState(m_drawListTag, pipelineStateDescriptor);
  95. RHI::InputStreamLayoutBuilder layoutBuilder;
  96. layoutBuilder.AddBuffer()->Channel("POSITION", RHI::Format::R32G32B32_FLOAT);
  97. layoutBuilder.AddBuffer()->Channel("NORMAL", RHI::Format::R32G32B32_FLOAT);
  98. layoutBuilder.SetTopology(AZ::RHI::PrimitiveTopology::TriangleList);
  99. pipelineStateDescriptor.m_inputStreamLayout = layoutBuilder.End();
  100. m_pipelineState = shader->AcquirePipelineState(pipelineStateDescriptor);
  101. if (!m_pipelineState)
  102. {
  103. AZ_Error("Render", false, "Failed to acquire default pipeline state for shader %s", shaderFilepath);
  104. }
  105. // Get the root constants layout from the pipeline descriptor.
  106. auto rootConstantsLayout = pipelineStateDescriptor.m_pipelineLayoutDescriptor->GetRootConstantsLayout();
  107. // Cache the index for the matrix and material Id constants
  108. m_materialIdInputIndex = rootConstantsLayout->FindShaderInputIndex(Name{ "s_materialIndex" });
  109. m_modelMatrixInputIndex = rootConstantsLayout->FindShaderInputIndex(Name{ "s_objectMatrix" });
  110. // We use a constant data class to set the values of the constants.
  111. m_rootConstantData = RHI::ConstantsData(rootConstantsLayout);
  112. // Load shader resource group asset
  113. m_srg = AZ::RPI::ShaderResourceGroup::Create(shaderAsset, Name { "MaterialGroupSrg" });
  114. if (!m_srg)
  115. {
  116. AZ_Error("Render", false, "Failed to create shader resource group");
  117. return;
  118. }
  119. auto materialsInputIndex = m_srg->FindShaderInputConstantIndex(Name("m_materials"));
  120. struct MaterialInfo
  121. {
  122. AZ::Color m_color;
  123. };
  124. // "Material" array with colors
  125. MaterialInfo materials[] =
  126. {
  127. MaterialInfo{AZ::Color(1.f, 0.f, 0.f, 1.f)},
  128. MaterialInfo{AZ::Color(0.f,1.f, 0.f, 1.f)},
  129. MaterialInfo{AZ::Color(0.f, 0.f, 1.f, 1.f)},
  130. };
  131. for (uint32_t i = 0; i < AZ_ARRAY_SIZE(materials); ++i)
  132. {
  133. m_srg->SetConstant(materialsInputIndex, materials[i], i);
  134. }
  135. m_srg->Compile();
  136. m_streamIndices.resize(m_models.size());
  137. for (uint32_t i = 0; i < m_models.size(); ++i)
  138. {
  139. auto model = m_models[i];
  140. if (model)
  141. {
  142. Data::Instance<AZ::RPI::ModelLod> modelLod = model->GetLods()[0];
  143. m_streamIndices[i].resize(modelLod->GetMeshes().size());
  144. for (uint32_t j = 0; j < m_streamIndices[i].size(); ++j)
  145. {
  146. modelLod->GetStreamsForMesh(
  147. pipelineStateDescriptor.m_inputStreamLayout, m_streamIndices[i][j], nullptr, shader->GetInputContract(),
  148. j);
  149. }
  150. }
  151. }
  152. }
  153. }
  154. void RootConstantsExampleComponent::SetupScene()
  155. {
  156. Render::DirectionalLightFeatureProcessorInterface* const featureProcessor =
  157. m_scene->GetFeatureProcessor<Render::DirectionalLightFeatureProcessorInterface>();
  158. m_directionalLightFeatureProcessor = featureProcessor;
  159. // Light creation
  160. m_directionalLightHandle = featureProcessor->AcquireLight();
  161. // Light direction
  162. const auto lightTransform = Transform::CreateLookAt(
  163. Vector3(100, 100, 100),
  164. Vector3::CreateZero());
  165. featureProcessor->SetDirection(m_directionalLightHandle, lightTransform.GetBasis(1));
  166. m_modelMatrices.resize(m_models.size());
  167. for (uint32_t i = 0; i < m_modelMatrices.size(); ++i)
  168. {
  169. m_modelMatrices[i] = AZ::Matrix4x4::CreateIdentity();
  170. }
  171. }
  172. void RootConstantsExampleComponent::Activate()
  173. {
  174. m_dynamicDraw = RPI::GetDynamicDraw();
  175. PrepareRenderData();
  176. SetupScene();
  177. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable,
  178. azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
  179. AZ::TickBus::Handler::BusConnect();
  180. ExampleComponentRequestBus::Handler::BusConnect(GetEntityId());
  181. }
  182. void RootConstantsExampleComponent::Deactivate()
  183. {
  184. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  185. ExampleComponentRequestBus::Handler::BusDisconnect();
  186. AZ::TickBus::Handler::BusDisconnect();
  187. m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
  188. m_pipelineState = nullptr;
  189. m_drawListTag.Reset();
  190. m_srg = nullptr;
  191. m_modelMatrices.clear();
  192. m_models.clear();
  193. m_streamIndices.clear();
  194. }
  195. void RootConstantsExampleComponent::OnTick([[maybe_unused]] float deltaTime, AZ::ScriptTimePoint timePoint)
  196. {
  197. // Model positions
  198. const AZ::Vector3 translations[]
  199. {
  200. AZ::Vector3{5.0f, 0, 0},
  201. AZ::Vector3{-5.0f, 0, 0},
  202. AZ::Vector3{0, 0, 0},
  203. };
  204. const float rotationSpeed[]
  205. {
  206. 16.0f,
  207. -5.0f,
  208. 25.0f
  209. };
  210. for (uint32_t i = 0; i < m_models.size(); ++i)
  211. {
  212. const float baseAngle = fmod(static_cast<float>(timePoint.GetSeconds()) * AZ::Constants::TwoPi / rotationSpeed[i], AZ::Constants::TwoPi);
  213. m_modelMatrices[i] = AZ::Matrix4x4::CreateTranslation(translations[i]) * AZ::Matrix4x4::CreateRotationZ(baseAngle);
  214. DrawModel(i);
  215. }
  216. // Camera configuration
  217. {
  218. Camera::Configuration config;
  219. Camera::CameraRequestBus::EventResult(
  220. config,
  221. GetCameraEntityId(),
  222. &Camera::CameraRequestBus::Events::GetCameraConfiguration);
  223. m_directionalLightFeatureProcessor->SetCameraConfiguration(
  224. m_directionalLightHandle,
  225. config);
  226. }
  227. // Camera transform
  228. {
  229. Transform transform = Transform::CreateIdentity();
  230. TransformBus::EventResult(
  231. transform,
  232. GetCameraEntityId(),
  233. &TransformBus::Events::GetWorldTM);
  234. m_directionalLightFeatureProcessor->SetCameraTransform(
  235. m_directionalLightHandle, transform);
  236. }
  237. }
  238. void RootConstantsExampleComponent::DrawModel(uint32_t modelIndex)
  239. {
  240. // Update the values of the matrix and the material index.
  241. m_rootConstantData.SetConstant(m_materialIdInputIndex, modelIndex);
  242. m_rootConstantData.SetConstant(m_modelMatrixInputIndex, m_modelMatrices[modelIndex]);
  243. auto& model = m_models[modelIndex];
  244. if (model)
  245. {
  246. AZStd::span<AZ::RPI::ModelLod::Mesh> meshes = model->GetLods()[0]->GetMeshes();
  247. for (uint32_t i = 0; i < meshes.size(); ++i)
  248. {
  249. auto& mesh = meshes[i];
  250. // Build draw packet and set the values of the inline constants.
  251. RHI::DrawPacketBuilder drawPacketBuilder{RHI::MultiDevice::DefaultDevice};
  252. drawPacketBuilder.Begin(nullptr);
  253. drawPacketBuilder.SetGeometryView(&mesh);
  254. drawPacketBuilder.SetRootConstants(m_rootConstantData.GetConstantData());
  255. drawPacketBuilder.AddShaderResourceGroup(m_srg->GetRHIShaderResourceGroup());
  256. RHI::DrawPacketBuilder::DrawRequest drawRequest;
  257. drawRequest.m_listTag = m_drawListTag;
  258. drawRequest.m_pipelineState = m_pipelineState.get();
  259. drawRequest.m_streamIndices = m_streamIndices[modelIndex][i];
  260. drawRequest.m_sortKey = 0;
  261. drawPacketBuilder.AddDrawItem(drawRequest);
  262. auto drawPacket{drawPacketBuilder.End()};
  263. m_dynamicDraw->AddDrawPacket(m_scene, AZStd::move(drawPacket));
  264. }
  265. }
  266. }
  267. }