/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace AZ { namespace Render { class ReflectionProbeFeatureProcessor; using BuildCubeMapCallback = AZStd::function; // shared data for rendering reflections, loaded and stored by the ReflectionProbeFeatureProcessor and passed to all probes struct ReflectionRenderData { AZStd::array m_boxPositionBufferView; RHI::IndexBufferView m_boxIndexBufferView; uint32_t m_boxIndexCount = 0; RPI::Ptr m_stencilPipelineState; RPI::Ptr m_blendWeightPipelineState; RPI::Ptr m_renderOuterPipelineState; RPI::Ptr m_renderInnerPipelineState; Data::Instance m_stencilShader; RHI::Ptr m_stencilSrgLayout; Data::Instance m_blendWeightShader; RHI::Ptr m_blendWeightSrgLayout; Data::Instance m_renderOuterShader; RHI::Ptr m_renderOuterSrgLayout; Data::Instance m_renderInnerShader; RHI::Ptr m_renderInnerSrgLayout; RHI::DrawListTag m_stencilDrawListTag; RHI::DrawListTag m_blendWeightDrawListTag; RHI::DrawListTag m_renderOuterDrawListTag; RHI::DrawListTag m_renderInnerDrawListTag; RHI::ShaderInputNameIndex m_modelToWorldStencilConstantIndex = "m_modelToWorld"; RHI::ShaderInputNameIndex m_modelToWorldRenderConstantIndex = "m_modelToWorld"; RHI::ShaderInputNameIndex m_modelToWorldInverseRenderConstantIndex = "m_modelToWorldInverse"; RHI::ShaderInputNameIndex m_outerObbHalfLengthsRenderConstantIndex = "m_outerObbHalfLengths"; RHI::ShaderInputNameIndex m_innerObbHalfLengthsRenderConstantIndex = "m_innerObbHalfLengths"; RHI::ShaderInputNameIndex m_useParallaxCorrectionRenderConstantIndex = "m_useParallaxCorrection"; RHI::ShaderInputNameIndex m_exposureConstantIndex = "m_exposure"; RHI::ShaderInputNameIndex m_reflectionCubeMapRenderImageIndex = "m_reflectionCubeMap"; }; // ReflectionProbe manages all aspects of a single probe, including rendering, visualization, and cubemap generation class ReflectionProbe final : public AZ::Data::AssetBus::MultiHandler { public: ReflectionProbe() = default; ~ReflectionProbe(); void Init(RPI::Scene* scene, ReflectionRenderData* reflectionRenderData); void Simulate(uint32_t probeIndex); void OnRenderEnd(); const Vector3& GetPosition() const { return m_transform.GetTranslation(); } const AZ::Transform& GetTransform() const { return m_transform; } void SetTransform(const AZ::Transform& transform); const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } void SetOuterExtents(const AZ::Vector3& outerExtents); const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; } void SetInnerExtents(const AZ::Vector3& innerExtents); const Obb& GetOuterObbWs() const { return m_outerObbWs; } const Obb& GetInnerObbWs() const { return m_innerObbWs; } const Data::Instance& GetCubeMapImage() const { return m_cubeMapImage; } void SetCubeMapImage(const Data::Instance& cubeMapImage, const AZStd::string& relativePath); const AZStd::string& GetCubeMapRelativePath() const { return m_cubeMapRelativePath; } bool GetUseParallaxCorrection() const { return m_useParallaxCorrection; } void SetUseParallaxCorrection(bool useParallaxCorrection) { m_useParallaxCorrection = useParallaxCorrection; } // initiates the cubemap bake and invokes the callback when all faces of the cubemap are rendered void BuildCubeMap(BuildCubeMapCallback callback); bool IsBuildingCubeMap() { return m_buildingCubeMap; } // called by the feature processor so the probe can set the default view for the pipeline void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline); // enables or disables rendering of the visualization sphere void ShowVisualization(bool showVisualization); // the exposure to use when rendering meshes with this probe's cubemap void SetRenderExposure(float renderExposure); float GetRenderExposure() const { return m_renderExposure; } // the exposure to use when baking the probe cubemap void SetBakeExposure(float bakeExposure); float GetBakeExposure() const { return m_bakeExposure; } private: AZ_DISABLE_COPY_MOVE(ReflectionProbe); const RHI::DrawPacket* BuildDrawPacket( const Data::Instance& srg, const RPI::Ptr& pipelineState, const RHI::DrawListTag& drawListTag, uint32_t stencilRef); void UpdateCulling(); // AZ::Data::AssetBus::Handler overrides... void OnAssetReady(Data::Asset asset) override; void OnAssetError(Data::Asset asset) override; // scene RPI::Scene* m_scene = nullptr; // probe volume transform AZ::Transform m_transform = AZ::Transform::CreateIdentity(); // extents of the probe volume AZ::Vector3 m_outerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); AZ::Vector3 m_innerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); // probe volume OBBs (world space), built from position and extents Obb m_outerObbWs; Obb m_innerObbWs; // cubemap Data::Instance m_cubeMapImage; AZStd::string m_cubeMapRelativePath; bool m_useParallaxCorrection = false; // probe visualization AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; Data::Asset m_visualizationModelAsset; Data::Asset m_visualizationMaterialAsset; AZ::Render::MeshFeatureProcessorInterface::MeshHandle m_visualizationMeshHandle; // reflection rendering ReflectionRenderData* m_reflectionRenderData = nullptr; Data::Instance m_stencilSrg; Data::Instance m_blendWeightSrg; Data::Instance m_renderOuterSrg; Data::Instance m_renderInnerSrg; RHI::ConstPtr m_stencilDrawPacket; RHI::ConstPtr m_blendWeightDrawPacket; RHI::ConstPtr m_renderOuterDrawPacket; RHI::ConstPtr m_renderInnerDrawPacket; float m_renderExposure = 0.0f; float m_bakeExposure = 0.0f; bool m_updateSrg = false; const RHI::DrawItemSortKey InvalidSortKey = static_cast(-1); RHI::DrawItemSortKey m_sortKey = InvalidSortKey; // culling RPI::Cullable m_cullable; // probe baking RPI::Ptr m_environmentCubeMapPass = nullptr; RPI::RenderPipelineId m_environmentCubeMapPipelineId; BuildCubeMapCallback m_callback; RHI::ShaderInputNameIndex m_globalIblExposureConstantIndex = "m_iblExposure"; RHI::ShaderInputNameIndex m_skyBoxExposureConstantIndex = "m_cubemapExposure"; float m_previousGlobalIblExposure = 0.0f; float m_previousSkyBoxExposure = 0.0f; bool m_buildingCubeMap = false; }; } // namespace Render } // namespace AZ