CubeMapRenderer.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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 <CubeMapCapture/CubeMapRenderer.h>
  9. #include <Atom/RPI.Public/Pass/Pass.h>
  10. #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
  11. #include <Atom/RPI.Public/RenderPipeline.h>
  12. #include <Atom/RPI.Public/View.h>
  13. #include <Atom/RPI.Reflect/Pass/EnvironmentCubeMapPassData.h>
  14. namespace AZ
  15. {
  16. namespace Render
  17. {
  18. void CubeMapRenderer::StartRender(RenderCubeMapCallback callback, const AZ::Transform& transform, float exposure)
  19. {
  20. AZ_Assert(m_scene, "CubeMapRenderer::StartRender called without a valid scene");
  21. AZ_Assert(m_renderingCubeMap == false, "CubeMapRenderer::StartRender called while a cubemap render was already in progress");
  22. if (m_renderingCubeMap)
  23. {
  24. return;
  25. }
  26. m_renderingCubeMap = true;
  27. m_callback = callback;
  28. m_exposure = exposure;
  29. AZ::RPI::RenderPipelineDescriptor environmentCubeMapPipelineDesc;
  30. environmentCubeMapPipelineDesc.m_mainViewTagName = "MainCamera";
  31. environmentCubeMapPipelineDesc.m_renderSettings.m_multisampleState = RPI::RPISystemInterface::Get()->GetApplicationMultisampleState();
  32. environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_width = RPI::EnvironmentCubeMapPass::CubeMapFaceSize;
  33. environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_height = RPI::EnvironmentCubeMapPass::CubeMapFaceSize;
  34. environmentCubeMapPipelineDesc.m_allowModification = true; // Enable pipeline modification since we need to have GI lighting for the baking
  35. // create a unique name for the pipeline
  36. AZ::Uuid uuid = AZ::Uuid::CreateRandom();
  37. AZStd::string uuidString;
  38. uuid.ToString(uuidString);
  39. environmentCubeMapPipelineDesc.m_name = AZStd::string::format("EnvironmentCubeMapPipeline_%s", uuidString.c_str());
  40. RPI::RenderPipelinePtr environmentCubeMapPipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(environmentCubeMapPipelineDesc);
  41. m_environmentCubeMapPipelineId = environmentCubeMapPipeline->GetId();
  42. AZStd::shared_ptr<RPI::EnvironmentCubeMapPassData> passData = AZStd::make_shared<RPI::EnvironmentCubeMapPassData>();
  43. passData->m_position = transform.GetTranslation();
  44. RPI::PassDescriptor environmentCubeMapPassDescriptor(Name("EnvironmentCubeMapPass"));
  45. environmentCubeMapPassDescriptor.m_passData = passData;
  46. m_environmentCubeMapPass = RPI::EnvironmentCubeMapPass::Create(environmentCubeMapPassDescriptor);
  47. m_environmentCubeMapPass->SetRenderPipeline(environmentCubeMapPipeline.get());
  48. const RPI::Ptr<RPI::ParentPass>& rootPass = environmentCubeMapPipeline->GetRootPass();
  49. rootPass->AddChild(m_environmentCubeMapPass);
  50. // store the current exposure values
  51. Data::Instance<RPI::ShaderResourceGroup> sceneSrg = m_scene->GetShaderResourceGroup();
  52. m_previousGlobalIblExposure = sceneSrg->GetConstant<float>(m_globalIblExposureConstantIndex);
  53. m_previousSkyBoxExposure = sceneSrg->GetConstant<float>(m_skyBoxExposureConstantIndex);
  54. // add the pipeline to the scene
  55. m_scene->AddRenderPipeline(environmentCubeMapPipeline);
  56. }
  57. void CubeMapRenderer::Update()
  58. {
  59. if (m_renderingCubeMap)
  60. {
  61. Data::Instance<RPI::ShaderResourceGroup> sceneSrg = m_scene->GetShaderResourceGroup();
  62. // set exposures to the user specified value while baking the cubemap
  63. sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_exposure);
  64. sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_exposure);
  65. }
  66. }
  67. void CubeMapRenderer::CheckAndRemovePipeline()
  68. {
  69. if (m_environmentCubeMapPass && m_environmentCubeMapPass->IsFinished())
  70. {
  71. Data::Instance<RPI::ShaderResourceGroup> sceneSrg = m_scene->GetShaderResourceGroup();
  72. // all faces of the cubemap have been rendered, invoke the callback
  73. m_callback(m_environmentCubeMapPass->GetTextureData(), m_environmentCubeMapPass->GetTextureFormat());
  74. // restore exposures
  75. sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_previousGlobalIblExposure);
  76. sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_previousSkyBoxExposure);
  77. m_renderingCubeMap = false;
  78. // remove the cubemap pipeline
  79. // Note: this must not be called in the scope of a feature processor Simulate or Render to avoid a race condition with other feature processors
  80. m_scene->RemoveRenderPipeline(m_environmentCubeMapPipelineId);
  81. m_environmentCubeMapPass = nullptr;
  82. }
  83. }
  84. void CubeMapRenderer::SetDefaultView(RPI::RenderPipeline* renderPipeline)
  85. {
  86. // check for an active cubemap build and matching pipeline
  87. if (m_environmentCubeMapPass
  88. && m_renderingCubeMap
  89. && m_environmentCubeMapPipelineId == renderPipeline->GetId())
  90. {
  91. m_environmentCubeMapPass->SetDefaultView();
  92. }
  93. }
  94. } // namespace Render
  95. } // namespace AZ