RootConstantsExampleComponent.cpp 13 KB

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