DynamicDrawExampleComponent.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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 <DynamicDrawExampleComponent.h>
  9. #include <SampleComponentManager.h>
  10. #include <Automation/ScriptableImGui.h>
  11. #include <Automation/ScriptRunnerBus.h>
  12. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  13. #include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
  14. #include <Atom/RPI.Public/Pass/PassFilter.h>
  15. #include <Atom/RPI.Public/Pass/RasterPass.h>
  16. #include <Atom/RPI.Public/RPIUtils.h>
  17. namespace AtomSampleViewer
  18. {
  19. void DynamicDrawExampleComponent::Reflect(AZ::ReflectContext* context)
  20. {
  21. if (AZ::SerializeContext * serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  22. {
  23. serializeContext->Class<DynamicDrawExampleComponent, AZ::Component>()
  24. ->Version(0)
  25. ;
  26. }
  27. }
  28. DynamicDrawExampleComponent::DynamicDrawExampleComponent()
  29. {
  30. m_sampleName = "DynamicDrawExampleComponent";
  31. }
  32. void DynamicDrawExampleComponent::Activate()
  33. {
  34. using namespace AZ;
  35. // List of all assets this example needs.
  36. AZStd::vector<AZ::AssetCollectionAsyncLoader::AssetToLoadInfo> assetList = {
  37. {"Shaders/dynamicdraw/dynamicdrawexample.azshader", azrtti_typeid<AZ::RPI::ShaderAsset>()},
  38. };
  39. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScript);
  40. PreloadAssets(assetList);
  41. }
  42. void DynamicDrawExampleComponent::OnAllAssetsReadyActivate()
  43. {
  44. AZ::TickBus::Handler::BusConnect();
  45. m_imguiSidebar.Activate();
  46. using namespace AZ;
  47. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable,
  48. azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
  49. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequestBus::Events::SetPosition, Vector3(-0.11f, -3.01f, -0.02f));
  50. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequestBus::Events::SetHeading, DegToRad(-4.0f));
  51. AZ::Debug::NoClipControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::NoClipControllerRequestBus::Events::SetPitch, DegToRad(1.9f));
  52. AZStd::vector<RPI::DynamicDrawContext::VertexChannel> vertexChannels =
  53. {
  54. { "POSITION", RHI::Format::R32G32B32_FLOAT },
  55. { "COLOR", RHI::Format::R32G32B32A32_FLOAT }
  56. };
  57. // Create and initialize dynamic draw context
  58. m_dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext();
  59. const char* shaderFilepath = "Shaders/dynamicdraw/dynamicdrawexample.azshader";
  60. Data::Asset<RPI::ShaderAsset> shaderAsset = m_assetLoadManager.GetAsset<RPI::ShaderAsset>(shaderFilepath);
  61. m_dynamicDraw->InitShader(shaderAsset);
  62. m_dynamicDraw->InitVertexFormat(vertexChannels);
  63. m_dynamicDraw->AddDrawStateOptions(RPI::DynamicDrawContext::DrawStateOptions::BlendMode | RPI::DynamicDrawContext::DrawStateOptions::PrimitiveType
  64. | RPI::DynamicDrawContext::DrawStateOptions::DepthState | RPI::DynamicDrawContext::DrawStateOptions::FaceCullMode);
  65. m_dynamicDraw->SetOutputScope(m_scene);
  66. m_dynamicDraw->EndInit();
  67. Data::Instance<RPI::ShaderResourceGroup> contextSrg = m_dynamicDraw->GetPerContextSrg();
  68. if (contextSrg)
  69. {
  70. auto index = contextSrg->FindShaderInputConstantIndex(Name("m_scale"));
  71. contextSrg->SetConstant(index, 1);
  72. contextSrg->Compile();
  73. }
  74. AZ_Assert(m_dynamicDraw->IsVertexSizeValid(sizeof(ExampleVertex)), "Invalid vertex format");
  75. // Dynamic draw for pass
  76. m_dynamicDraw1ForPass = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext();
  77. m_dynamicDraw2ForPass = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext();
  78. // Get auxGeom pass from the current render pipeline
  79. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(
  80. Name("AuxGeomPass"),
  81. m_scene);
  82. RPI::RasterPass* auxGeomPass = azrtti_cast<RPI::RasterPass*>(AZ::RPI::PassSystemInterface::Get()->FindFirstPass(passFilter));
  83. AZ_Assert(auxGeomPass, "AuxGeomPass should be a RasterPass or a derived RasterPass");
  84. m_dynamicDraw1ForPass->InitShader(shaderAsset);
  85. m_dynamicDraw1ForPass->InitVertexFormat(vertexChannels);
  86. m_dynamicDraw1ForPass->AddDrawStateOptions(RPI::DynamicDrawContext::DrawStateOptions::BlendMode
  87. | RPI::DynamicDrawContext::DrawStateOptions::DepthState);
  88. m_dynamicDraw1ForPass->SetOutputScope(auxGeomPass);
  89. m_dynamicDraw1ForPass->EndInit();
  90. m_dynamicDraw2ForPass->InitShader(shaderAsset);
  91. m_dynamicDraw2ForPass->InitVertexFormat(vertexChannels);
  92. m_dynamicDraw2ForPass->AddDrawStateOptions(RPI::DynamicDrawContext::DrawStateOptions::BlendMode
  93. | RPI::DynamicDrawContext::DrawStateOptions::DepthState);
  94. m_dynamicDraw2ForPass->SetOutputScope(auxGeomPass);
  95. m_dynamicDraw2ForPass->EndInit();
  96. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
  97. }
  98. void DynamicDrawExampleComponent::Deactivate()
  99. {
  100. using namespace AZ;
  101. m_imguiSidebar.Deactivate();
  102. TickBus::Handler::BusDisconnect();
  103. AZ::Debug::CameraControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  104. m_dynamicDraw = nullptr;
  105. m_contextSrg = nullptr;
  106. m_dynamicDraw1ForPass = nullptr;
  107. m_dynamicDraw2ForPass = nullptr;
  108. }
  109. void DynamicDrawExampleComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  110. {
  111. using namespace AZ;
  112. if (m_imguiSidebar.Begin())
  113. {
  114. ScriptableImGui::Checkbox("CullMode::None", &m_showCullModeNull);
  115. ScriptableImGui::Checkbox("CullMode: Front", &m_showCullModeFront);
  116. ScriptableImGui::Checkbox("CullMode: Back", &m_showCullModeBack);
  117. ScriptableImGui::Checkbox("PrimitiveTopology: LineList", &m_showLineList);
  118. ScriptableImGui::Checkbox("Alpha Blend", &m_showAlphaBlend);
  119. ScriptableImGui::Checkbox("Alpha Additive", &m_showAlphaAdditive);
  120. ScriptableImGui::Checkbox("Per Draw Viewport", &m_showPerDrawViewport);
  121. ScriptableImGui::Checkbox("Sorting", &m_showSorting);
  122. m_imguiSidebar.End();
  123. }
  124. // draw srg with default offset
  125. Data::Instance<RPI::ShaderResourceGroup> drawSrg = m_dynamicDraw->NewDrawSrg();
  126. auto index = drawSrg->FindShaderInputConstantIndex(Name("m_positionOffset"));
  127. drawSrg->SetConstant(index, Vector3(0, 0, 0));
  128. drawSrg->Compile();
  129. // Tetrahedron
  130. const uint32_t TetrahedronVertexCount = 12;
  131. const uint32_t TetrahedronWireframeIndexCount = 12;
  132. float positions[4][3] =
  133. {
  134. { 0.2, 0.2f, 0.2f },
  135. { 0.2, -0.2f, -0.2f },
  136. { -0.2, 0.2f, -0.2f },
  137. { -0.2, -0.2f, 0.2f }
  138. };
  139. float colors[4][4] = { { 1, 0, 0, 0.5f }, { 0, 1, 0, 0.5f }, { 0, 0, 1, 0.5f }, {1, 1, 0, 0.5f}};
  140. ExampleVertex tetrahedronVerts[TetrahedronVertexCount] = {
  141. ExampleVertex{positions[0], colors[0]}, // 0
  142. ExampleVertex{positions[3], colors[0]}, // 3
  143. ExampleVertex{positions[1], colors[0]}, // 1
  144. ExampleVertex{positions[0], colors[1]}, // 0
  145. ExampleVertex{positions[1], colors[1]}, // 1
  146. ExampleVertex{positions[2], colors[1]}, // 2
  147. ExampleVertex{positions[0], colors[2]}, // 0
  148. ExampleVertex{positions[2], colors[2]}, // 2
  149. ExampleVertex{positions[3], colors[2]}, // 3
  150. ExampleVertex{positions[1], colors[3]}, // 1
  151. ExampleVertex{positions[3], colors[3]}, // 3
  152. ExampleVertex{positions[2], colors[3]} // 2
  153. };
  154. ExampleVertex tetrahedronWireFrameVerts[4] = {
  155. ExampleVertex{ positions[0], colors[0] },
  156. ExampleVertex{ positions[1], colors[1] },
  157. ExampleVertex{ positions[2], colors[2] },
  158. ExampleVertex{ positions[3], colors[3] }
  159. };
  160. u16 tetrahedronWireframeIndices[TetrahedronWireframeIndexCount] =
  161. {
  162. 0, 1,
  163. 0, 2,
  164. 0, 3,
  165. 1, 2,
  166. 2, 3,
  167. 3, 1
  168. };
  169. // Enable depth test and write
  170. RHI::DepthState depthState;
  171. depthState.m_enable = true;
  172. depthState.m_writeMask = RHI::DepthWriteMask::All;
  173. depthState.m_func = RHI::ComparisonFunc::GreaterEqual;
  174. m_dynamicDraw->SetDepthState(depthState);
  175. // Disable blend
  176. RHI::TargetBlendState blendState;
  177. blendState.m_enable = false;
  178. m_dynamicDraw->SetTarget0BlendState(blendState);
  179. float xPos = -1.5f;
  180. const float xOffset = 0.5f;
  181. // no cull
  182. if (m_showCullModeNull)
  183. {
  184. m_dynamicDraw->SetCullMode(RHI::CullMode::None);
  185. drawSrg = m_dynamicDraw->NewDrawSrg();
  186. drawSrg->SetConstant(index, Vector3(xPos, 0, 0));
  187. drawSrg->Compile();
  188. m_dynamicDraw->DrawLinear(tetrahedronVerts, TetrahedronVertexCount, drawSrg);
  189. }
  190. //front cull
  191. xPos += xOffset;
  192. if (m_showCullModeFront)
  193. {
  194. m_dynamicDraw->SetCullMode(RHI::CullMode::Front);
  195. drawSrg = m_dynamicDraw->NewDrawSrg();
  196. drawSrg->SetConstant(index, Vector3(xPos, 0, 0));
  197. drawSrg->Compile();
  198. m_dynamicDraw->DrawLinear(tetrahedronVerts, TetrahedronVertexCount, drawSrg);
  199. m_dynamicDraw->SetCullMode(RHI::CullMode::None);
  200. }
  201. // back cull
  202. xPos += xOffset;
  203. if (m_showCullModeBack)
  204. {
  205. m_dynamicDraw->SetCullMode(RHI::CullMode::Back);
  206. drawSrg = m_dynamicDraw->NewDrawSrg();
  207. drawSrg->SetConstant(index, Vector3(xPos, 0, 0));
  208. drawSrg->Compile();
  209. m_dynamicDraw->DrawLinear(tetrahedronVerts, TetrahedronVertexCount, drawSrg);
  210. m_dynamicDraw->SetCullMode(RHI::CullMode::None);
  211. }
  212. // Draw line lists
  213. xPos += xOffset;
  214. if (m_showLineList)
  215. {
  216. drawSrg = m_dynamicDraw->NewDrawSrg();
  217. drawSrg->SetConstant(index, Vector3(xPos, 0, 0));
  218. drawSrg->Compile();
  219. m_dynamicDraw->SetPrimitiveType(RHI::PrimitiveTopology::LineList);
  220. m_dynamicDraw->DrawIndexed(tetrahedronWireFrameVerts, 4, tetrahedronWireframeIndices, TetrahedronWireframeIndexCount, RHI::IndexFormat::Uint16, drawSrg);
  221. m_dynamicDraw->SetPrimitiveType(RHI::PrimitiveTopology::TriangleList);
  222. }
  223. // disable depth write
  224. depthState.m_writeMask = RHI::DepthWriteMask::Zero;
  225. m_dynamicDraw->SetDepthState(depthState);
  226. // alpha blend
  227. xPos += xOffset;
  228. if (m_showAlphaBlend)
  229. {
  230. blendState.m_enable = true;
  231. blendState.m_blendOp = RHI::BlendOp::Add;
  232. blendState.m_blendSource = RHI::BlendFactor::AlphaSource;
  233. blendState.m_blendDest = RHI::BlendFactor::AlphaSourceInverse;
  234. m_dynamicDraw->SetTarget0BlendState(blendState);
  235. drawSrg = m_dynamicDraw->NewDrawSrg();
  236. drawSrg->SetConstant(index, Vector3(xPos, 0, 0));
  237. drawSrg->Compile();
  238. m_dynamicDraw->DrawLinear(tetrahedronVerts, TetrahedronVertexCount, drawSrg);
  239. }
  240. // alpha additive
  241. xPos += xOffset;
  242. if (m_showAlphaAdditive)
  243. {
  244. blendState.m_enable = true;
  245. blendState.m_blendOp = RHI::BlendOp::Add;
  246. blendState.m_blendSource = RHI::BlendFactor::AlphaSource;
  247. blendState.m_blendDest = RHI::BlendFactor::One;
  248. m_dynamicDraw->SetTarget0BlendState(blendState);
  249. drawSrg = m_dynamicDraw->NewDrawSrg();
  250. drawSrg->SetConstant(index, Vector3(xPos, 0, 0));
  251. drawSrg->Compile();
  252. m_dynamicDraw->DrawLinear(tetrahedronVerts, TetrahedronVertexCount, drawSrg);
  253. }
  254. // enable depth write
  255. depthState.m_writeMask = RHI::DepthWriteMask::All;
  256. m_dynamicDraw->SetDepthState(depthState);
  257. // disable blend
  258. blendState.m_enable = false;
  259. m_dynamicDraw->SetTarget0BlendState(blendState);
  260. // per draw viewport
  261. xPos += xOffset;
  262. if (m_showPerDrawViewport)
  263. {
  264. m_dynamicDraw->SetViewport(RHI::Viewport(0, 200, 0, 200));
  265. drawSrg = m_dynamicDraw->NewDrawSrg();
  266. drawSrg->SetConstant(index, Vector3(0, 0, 0));
  267. drawSrg->Compile();
  268. m_dynamicDraw->DrawLinear(tetrahedronVerts, TetrahedronVertexCount, drawSrg);
  269. m_dynamicDraw->UnsetViewport();
  270. }
  271. // show draws from three different dynamic draw context with correct sorting
  272. if (m_showSorting)
  273. {
  274. float black[4] = {0, 0, 0, 1};
  275. float white[4] = {1, 1, 1, 1};
  276. float red[4] = {1, 0, 0, 1};
  277. float vertexPos[4][3] =
  278. {
  279. { -0.2, 0, 0.2f},
  280. { -0.2, 0, -0.2f},
  281. { 0.2, 0 , -0.2f},
  282. { 0.2, 0 , 0.2f}
  283. };
  284. ExampleVertex blackQuad[4] =
  285. {
  286. ExampleVertex{ vertexPos[0], black },
  287. ExampleVertex{ vertexPos[1], black },
  288. ExampleVertex{ vertexPos[2], black },
  289. ExampleVertex{ vertexPos[3], black }
  290. };
  291. ExampleVertex whiteQuad[4] =
  292. {
  293. ExampleVertex{ vertexPos[0], white },
  294. ExampleVertex{ vertexPos[1], white },
  295. ExampleVertex{ vertexPos[2], white },
  296. ExampleVertex{ vertexPos[3], white }
  297. };
  298. ExampleVertex redQuad[4] =
  299. {
  300. ExampleVertex{ vertexPos[0], red },
  301. ExampleVertex{ vertexPos[1], red },
  302. ExampleVertex{ vertexPos[2], red },
  303. ExampleVertex{ vertexPos[3], red }
  304. };
  305. u16 quadIndics[6] =
  306. {
  307. 0, 1, 2,
  308. 0, 2, 3
  309. };
  310. // disable depth for all and rely on sorting
  311. depthState.m_writeMask = RHI::DepthWriteMask::Zero;
  312. m_dynamicDraw->SetDepthState(depthState);
  313. m_dynamicDraw1ForPass->SetDepthState(depthState);
  314. m_dynamicDraw2ForPass->SetDepthState(depthState);
  315. blendState.m_enable = false;
  316. m_dynamicDraw->SetTarget0BlendState(blendState);
  317. m_dynamicDraw1ForPass->SetTarget0BlendState(blendState);
  318. m_dynamicDraw2ForPass->SetTarget0BlendState(blendState);
  319. // draw two red quads via view
  320. drawSrg = m_dynamicDraw->NewDrawSrg();
  321. drawSrg->SetConstant(index, Vector3(-0.3f, 0, 0.7f));
  322. drawSrg->Compile();
  323. m_dynamicDraw->SetSortKey(0x200);
  324. m_dynamicDraw->DrawIndexed(redQuad, 4, quadIndics, 6, RHI::IndexFormat::Uint16, drawSrg);
  325. drawSrg = m_dynamicDraw->NewDrawSrg();
  326. drawSrg->SetConstant(index, Vector3(0.3f, 0, 0.7f));
  327. drawSrg->Compile();
  328. m_dynamicDraw->SetSortKey(0);
  329. m_dynamicDraw->DrawIndexed(redQuad, 4, quadIndics, 6, RHI::IndexFormat::Uint16, drawSrg);
  330. // draw two white quads via ddc1
  331. drawSrg = m_dynamicDraw1ForPass->NewDrawSrg();
  332. drawSrg->SetConstant(index, Vector3(-0.3f, 0, 0.8f));
  333. drawSrg->Compile();
  334. m_dynamicDraw1ForPass->SetSortKey(0x100);
  335. m_dynamicDraw1ForPass->DrawIndexed(whiteQuad, 4, quadIndics, 6, RHI::IndexFormat::Uint16, drawSrg);
  336. drawSrg = m_dynamicDraw1ForPass->NewDrawSrg();
  337. drawSrg->SetConstant(index, Vector3(0.3f, 0, 0.8f));
  338. drawSrg->Compile();
  339. m_dynamicDraw1ForPass->SetSortKey(0x100);
  340. m_dynamicDraw1ForPass->DrawIndexed(whiteQuad, 4, quadIndics, 6, RHI::IndexFormat::Uint16, drawSrg);
  341. // draw two black quads via dcc2
  342. drawSrg = m_dynamicDraw2ForPass->NewDrawSrg();
  343. drawSrg->SetConstant(index, Vector3(-0.3f, 0, 0.9f));
  344. drawSrg->Compile();
  345. m_dynamicDraw2ForPass->SetSortKey(0);
  346. m_dynamicDraw2ForPass->DrawIndexed(blackQuad, 4, quadIndics, 6, RHI::IndexFormat::Uint16, drawSrg);
  347. drawSrg = m_dynamicDraw2ForPass->NewDrawSrg();
  348. drawSrg->SetConstant(index, Vector3(0.3f, 0, 0.9f));
  349. drawSrg->Compile();
  350. m_dynamicDraw2ForPass->SetSortKey(0x200);
  351. m_dynamicDraw2ForPass->DrawIndexed(blackQuad, 4, quadIndics, 6, RHI::IndexFormat::Uint16, drawSrg);
  352. }
  353. }
  354. } // namespace AtomSampleViewer