diff --git a/Gems/Atom/Feature/Common/Assets/Materials/OcclusionCullingPlane/OcclusionCullingPlaneTransparentVisualization.material b/Gems/Atom/Feature/Common/Assets/Materials/OcclusionCullingPlane/OcclusionCullingPlaneTransparentVisualization.material new file mode 100644 index 0000000000..981e392eef --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/OcclusionCullingPlane/OcclusionCullingPlaneTransparentVisualization.material @@ -0,0 +1,22 @@ +{ + "materialType": "Materials\\Types\\StandardPBR.materialtype", + "propertyLayoutVersion": 3, + "properties": { + "general": { + "enableShadows": false, + "enableDirectionalLights": false, + "enablePunctualLights": false, + "enableAreaLights": false, + "enableIBL": true + }, + "baseColor": { + "color": [ 0.0, 1.0, 0.0 ] + }, + "opacity": { + "alphaSource": "None", + "doubleSided": true, + "factor": 0.25, + "mode": "TintedTransparent" + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Materials/OcclusionCullingPlane/OcclusionCullingPlaneVisualization.material b/Gems/Atom/Feature/Common/Assets/Materials/OcclusionCullingPlane/OcclusionCullingPlaneVisualization.material new file mode 100644 index 0000000000..4446cc2d9d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/OcclusionCullingPlane/OcclusionCullingPlaneVisualization.material @@ -0,0 +1,22 @@ +{ + "materialType": "Materials\\Types\\StandardPBR.materialtype", + "propertyLayoutVersion": 3, + "properties": { + "general": { + "enableShadows": false, + "enableDirectionalLights": false, + "enablePunctualLights": false, + "enableAreaLights": false, + "enableIBL": true + }, + "baseColor": { + "color": [ 0.0, 1.0, 0.0 ] + }, + "opacity": { + "alphaSource": "None", + "doubleSided": true, + "factor": 1.0, + "mode": "TintedTransparent" + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Models/OcclusionCullingPlane.fbx b/Gems/Atom/Feature/Common/Assets/Models/OcclusionCullingPlane.fbx new file mode 100644 index 0000000000..b274bfa282 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Models/OcclusionCullingPlane.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a1f8d75dcd85e8b4aa57f6c0c81af0300ff96915ba3c2b591095c215d5e1d8c +size 12072 diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessorInterface.h index 07a6179e78..8ffbb7f235 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessorInterface.h @@ -36,6 +36,8 @@ namespace AZ virtual bool IsValidOcclusionCullingPlaneHandle(const OcclusionCullingPlaneHandle& occlusionCullingPlane) const = 0; virtual void SetTransform(const OcclusionCullingPlaneHandle& occlusionCullingPlane, const AZ::Transform& transform) = 0; virtual void SetEnabled(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool enabled) = 0; + virtual void ShowVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool showVisualization) = 0; + virtual void SetTransparentVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool transparentVisualization) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlane.cpp b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlane.cpp new file mode 100644 index 0000000000..10004a72e4 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlane.cpp @@ -0,0 +1,113 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + static const char* OcclusionCullingPlaneDrawListTag("occlusioncullingplanevisualization"); + + OcclusionCullingPlane::~OcclusionCullingPlane() + { + Data::AssetBus::MultiHandler::BusDisconnect(); + m_meshFeatureProcessor->ReleaseMesh(m_visualizationMeshHandle); + } + + void OcclusionCullingPlane::Init(RPI::Scene* scene) + { + AZ_Assert(scene, "OcclusionCullingPlane::Init called with a null Scene pointer"); + + m_meshFeatureProcessor = scene->GetFeatureProcessor(); + + // load visualization plane model and material + m_visualizationModelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( + "Models/OcclusionCullingPlane.azmodel", + AZ::RPI::AssetUtils::TraceLevel::Assert); + + m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset); + m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true); + m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false); + m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity()); + + SetVisualizationMaterial(); + } + + void OcclusionCullingPlane::SetVisualizationMaterial() + { + AZStd::string materialAssetPath; + if (m_transparentVisualization) + { + materialAssetPath = "Materials/OcclusionCullingPlane/OcclusionCullingPlaneTransparentVisualization.azmaterial"; + } + else + { + materialAssetPath = "Materials/OcclusionCullingPlane/OcclusionCullingPlaneVisualization.azmaterial"; + } + + RPI::AssetUtils::TraceLevel traceLevel = AZ::RPI::AssetUtils::TraceLevel::Assert; + m_visualizationMaterialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath(materialAssetPath.c_str(), traceLevel); + m_visualizationMaterialAsset.QueueLoad(); + Data::AssetBus::MultiHandler::BusConnect(m_visualizationMaterialAsset.GetId()); + } + + void OcclusionCullingPlane::OnAssetReady(Data::Asset asset) + { + if (m_visualizationMaterialAsset.GetId() == asset.GetId()) + { + m_visualizationMaterialAsset = asset; + Data::AssetBus::MultiHandler::BusDisconnect(asset.GetId()); + + m_visualizationMaterial = AZ::RPI::Material::FindOrCreate(m_visualizationMaterialAsset); + m_meshFeatureProcessor->SetMaterialAssignmentMap(m_visualizationMeshHandle, m_visualizationMaterial); + } + } + + void OcclusionCullingPlane::OnAssetError(Data::Asset asset) + { + AZ_Error("OcclusionCullingPlane", false, "Failed to load OcclusionCullingPlane visualization asset %s", asset.ToString().c_str()); + Data::AssetBus::MultiHandler::BusDisconnect(asset.GetId()); + } + + void OcclusionCullingPlane::SetTransform(const AZ::Transform& transform) + { + m_transform = transform; + + // update visualization plane transform + m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform); + } + + void OcclusionCullingPlane::ShowVisualization(bool showVisualization) + { + if (m_showVisualization != showVisualization) + { + m_meshFeatureProcessor->SetVisible(m_visualizationMeshHandle, showVisualization); + SetVisualizationMaterial(); + } + } + + void OcclusionCullingPlane::SetTransparentVisualization(bool transparentVisualization) + { + if (m_transparentVisualization != transparentVisualization) + { + m_transparentVisualization = transparentVisualization; + SetVisualizationMaterial(); + } + } + + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlane.h b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlane.h new file mode 100644 index 0000000000..4701c4977f --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlane.h @@ -0,0 +1,65 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +namespace AZ +{ + namespace Render + { + //! This class represents an OcclusionCullingPlane which is used to cull meshes that are inside the view frustum + class OcclusionCullingPlane final + : public AZ::Data::AssetBus::MultiHandler + { + public: + OcclusionCullingPlane() = default; + ~OcclusionCullingPlane(); + + void Init(RPI::Scene* scene); + + void SetTransform(const AZ::Transform& transform); + const AZ::Transform& GetTransform() const { return m_transform; } + + void SetEnabled(bool enabled) { m_enabled = enabled; } + bool GetEnabled() const { return m_enabled; } + + // enables or disables rendering of the visualization plane + void ShowVisualization(bool showVisualization); + + // sets the visualization to transparent mode + void SetTransparentVisualization(bool transparentVisualization); + + private: + + void SetVisualizationMaterial(); + + // AZ::Data::AssetBus::Handler overrides... + void OnAssetReady(Data::Asset asset) override; + void OnAssetError(Data::Asset asset) override; + + AZ::Transform m_transform; + bool m_enabled = true; + bool m_showVisualization = true; + bool m_transparentVisualization = false; + + // visualization + AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; + Data::Asset m_visualizationModelAsset; + Data::Asset m_visualizationMaterialAsset; + Data::Instance m_visualizationMaterial; + AZ::Render::MeshFeatureProcessorInterface::MeshHandle m_visualizationMeshHandle; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.cpp index bed008a3da..b9866a925f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.cpp @@ -60,6 +60,7 @@ namespace AZ OcclusionCullingPlaneHandle OcclusionCullingPlaneFeatureProcessor::AddOcclusionCullingPlane(const AZ::Transform& transform) { AZStd::shared_ptr occlusionCullingPlane = AZStd::make_shared(); + occlusionCullingPlane->Init(GetParentScene()); occlusionCullingPlane->SetTransform(transform); m_occlusionCullingPlanes.push_back(occlusionCullingPlane); return occlusionCullingPlane; @@ -90,5 +91,17 @@ namespace AZ AZ_Assert(occlusionCullingPlane.get(), "Enable called with an invalid handle"); occlusionCullingPlane->SetEnabled(enabled); } + + void OcclusionCullingPlaneFeatureProcessor::ShowVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool showVisualization) + { + AZ_Assert(occlusionCullingPlane.get(), "ShowVisualization called with an invalid handle"); + occlusionCullingPlane->ShowVisualization(showVisualization); + } + + void OcclusionCullingPlaneFeatureProcessor::SetTransparentVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool transparentVisualization) + { + AZ_Assert(occlusionCullingPlane.get(), "SetTransparentVisualization called with an invalid handle"); + occlusionCullingPlane->SetTransparentVisualization(transparentVisualization); + } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h index 5319666745..211254742f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h @@ -13,29 +13,12 @@ #pragma once #include +#include namespace AZ { namespace Render { - //! This class represents an OcclusionCullingPlane which is used to cull meshes that are inside the view frustum - class OcclusionCullingPlane final - { - public: - OcclusionCullingPlane() = default; - ~OcclusionCullingPlane() = default; - - void SetTransform(const AZ::Transform& transform) { m_transform = transform; } - const AZ::Transform& GetTransform() const { return m_transform; } - - void SetEnabled(bool enabled) { m_enabled = enabled; } - bool GetEnabled() const { return m_enabled; } - - private: - AZ::Transform m_transform; - bool m_enabled = true; - }; - //! This class manages OcclusionCullingPlanes which are used to cull meshes that are inside the view frustum class OcclusionCullingPlaneFeatureProcessor final : public OcclusionCullingPlaneFeatureProcessorInterface @@ -54,6 +37,8 @@ namespace AZ bool IsValidOcclusionCullingPlaneHandle(const OcclusionCullingPlaneHandle& occlusionCullingPlane) const override { return (occlusionCullingPlane.get() != nullptr); } void SetTransform(const OcclusionCullingPlaneHandle& occlusionCullingPlane, const AZ::Transform& transform) override; void SetEnabled(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool enable) override; + void ShowVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool showVisualization) override; + void SetTransparentVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool transparentVisualization) override; // FeatureProcessor overrides void Activate() override; diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index c545a2c974..b796a5b356 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -175,6 +175,8 @@ set(FILES Source/MorphTargets/MorphTargetDispatchItem.h Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h Source/OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.cpp + Source/OcclusionCullingPlane/OcclusionCullingPlane.h + Source/OcclusionCullingPlane/OcclusionCullingPlane.cpp Source/PostProcess/PostProcessBase.cpp Source/PostProcess/PostProcessBase.h Source/PostProcess/PostProcessFeatureProcessor.cpp diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index e105f7bca5..d8ed850309 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -428,20 +428,52 @@ namespace AZ return MaskedOcclusionCulling::CullingResult::VISIBLE; } - // convert the bounding box of the visibility entry to NDC - AZ::Vector4 clipSpaceMin = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(visibleEntry->m_boundingVolume.GetMin()); - float depth = clipSpaceMin.GetW(); - AZ::Vector4 ndcMin = clipSpaceMin / clipSpaceMin.GetW(); + if (visibleEntry->m_boundingVolume.Contains(m_jobData->m_view->GetCameraTransform().GetTranslation())) + { + // camera is inside bounding volume + return MaskedOcclusionCulling::CullingResult::VISIBLE; + } - AZ::Vector4 clipSpaceMax = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(visibleEntry->m_boundingVolume.GetMax()); - depth = AZStd::min(depth, clipSpaceMax.GetW()); - AZ::Vector4 ndcMax = clipSpaceMax / clipSpaceMax.GetW(); + const Vector3& minBound = visibleEntry->m_boundingVolume.GetMin(); + const Vector3& maxBound = visibleEntry->m_boundingVolume.GetMax(); - Vector2 rectMin(AZStd::min(ndcMin.GetX(), ndcMax.GetX()), AZStd::min(ndcMin.GetY(), ndcMax.GetY())); - Vector2 rectMax(AZStd::max(ndcMin.GetX(), ndcMax.GetX()), AZStd::max(ndcMin.GetY(), ndcMax.GetY())); + // compute bounding volume corners + Vector4 corners[8]; + corners[0] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(minBound.GetX(), minBound.GetY(), minBound.GetZ(), 1.0f); + corners[1] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(minBound.GetX(), minBound.GetY(), maxBound.GetZ(), 1.0f); + corners[2] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(maxBound.GetX(), minBound.GetY(), maxBound.GetZ(), 1.0f); + corners[3] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(maxBound.GetX(), minBound.GetY(), minBound.GetZ(), 1.0f); + corners[4] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(minBound.GetX(), maxBound.GetY(), minBound.GetZ(), 1.0f); + corners[5] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(minBound.GetX(), maxBound.GetY(), maxBound.GetZ(), 1.0f); + corners[6] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(maxBound.GetX(), maxBound.GetY(), maxBound.GetZ(), 1.0f); + corners[7] = m_jobData->m_view->GetWorldToClipMatrix() * Vector4(maxBound.GetX(), maxBound.GetY(), minBound.GetZ(), 1.0f); + // find min clip-space depth and NDC min/max + float ndcMinX = FLT_MAX; + float ndcMinY = FLT_MAX; + float ndcMaxX = -FLT_MAX; + float ndcMaxY = -FLT_MAX; + float minDepth = FLT_MAX; + for (uint32_t index = 0; index < 8; ++index) + { + minDepth = AZStd::min(minDepth, corners[index].GetW()); + + // convert to NDC + corners[index] /= corners[index].GetW(); + + ndcMinX = AZStd::min(ndcMinX, corners[index].GetX()); + ndcMinY = AZStd::min(ndcMinY, corners[index].GetY()); + ndcMaxX = AZStd::max(ndcMaxX, corners[index].GetX()); + ndcMaxY = AZStd::max(ndcMaxY, corners[index].GetY()); + } + + if (minDepth < 0.00000001f) + { + return MaskedOcclusionCulling::VISIBLE; + } + // test against the occlusion buffer, which contains only the manually placed occlusion planes - return m_jobData->m_maskedOcclusionCulling->TestRect(rectMin.GetX(), rectMin.GetY(), rectMax.GetX(), rectMax.GetY(), depth); + return m_jobData->m_maskedOcclusionCulling->TestRect(ndcMinX, ndcMinY, ndcMaxX, ndcMaxY, minDepth); } }; @@ -480,15 +512,22 @@ namespace AZ MaskedOcclusionCulling* maskedOcclusionCulling = m_occlusionCullingPlanes.empty() ? nullptr : view.GetMaskedOcclusionCulling(); if (maskedOcclusionCulling) { - // frustum cull and sort the occlusion planes by view space distance, front-to-back + // frustum cull occlusion planes using OccluderEntry = AZStd::pair; AZStd::vector visibleOccluders; for (const AZ::Transform& transform : m_occlusionCullingPlanes) { - Aabb occluderAabb = Aabb::CreateCenterHalfExtents(transform.GetTranslation(), AZ::Vector3(AZ::Vector2(transform.GetUniformScale() / 2.0f))); - occluderAabb.SetMin(transform.TransformPoint(occluderAabb.GetMin())); - occluderAabb.SetMax(transform.TransformPoint(occluderAabb.GetMax())); - if (ShapeIntersection::Contains(frustum, occluderAabb)) + static const AZ::Vector3 BL(-0.5f, -0.5f, 0.0f); + static const AZ::Vector3 TR(0.5f, 0.5f, 0.0f); + + AZ::Vector3 P1 = transform.TransformPoint(BL); + AZ::Vector3 P2 = transform.TransformPoint(TR); + + AZ::Vector3 aabbMin = P1.GetMin(P2); + AZ::Vector3 aabbMax = P1.GetMax(P2); + + AZ::Aabb occluderAabb = Aabb::CreateFromMinMax(aabbMin, aabbMax); + if (ShapeIntersection::Overlaps(frustum, occluderAabb)) { // occluder is visible, compute view space distance and add to list float depth = (view.GetWorldToViewMatrix() * occluderAabb.GetMin()).GetZ(); @@ -498,9 +537,10 @@ namespace AZ } } + // sort the occlusion planes by view space distance, front-to-back AZStd::sort(visibleOccluders.begin(), visibleOccluders.end(), [](const OccluderEntry& LHS, const OccluderEntry& RHS) { - return LHS.second < RHS.second; + return LHS.second > RHS.second; }); for (const OccluderEntry& occluder : visibleOccluders) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index edae0f88b7..6e4dec112f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -28,6 +28,10 @@ namespace AZ { namespace RPI { + // fixed-size software occlusion culling buffer + const uint32_t MaskedSoftwareOcclusionCullingWidth = 1920; + const uint32_t MaskedSoftwareOcclusionCullingHeight = 1080; + ViewPtr View::CreateView(const AZ::Name& name, UsageFlags usage) { View* view = aznew View(name, usage); @@ -54,7 +58,7 @@ namespace AZ } m_maskedOcclusionCulling = MaskedOcclusionCulling::Create(); - m_maskedOcclusionCulling->SetResolution(1920, 1080); + m_maskedOcclusionCulling->SetResolution(MaskedSoftwareOcclusionCullingWidth, MaskedSoftwareOcclusionCullingHeight); } View::~View() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp index 9a655727d6..b027be3171 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp @@ -53,8 +53,12 @@ namespace AZ editContext->Class( "OcclusionCullingPlaneComponentConfig", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->ClassElement(AZ::Edit::ClassElements::Group, "Settings") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &OcclusionCullingPlaneComponentConfig::m_showVisualization, "Show Visualization", "Show the occlusion culling plane visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &OcclusionCullingPlaneComponentConfig::m_transparentVisualization, "Transparent Visualization", "Sets the occlusion culling plane visualization as transparent") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.cpp index bd03bec0f4..cf8107776f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.cpp @@ -38,7 +38,9 @@ namespace AZ { serializeContext->Class() ->Version(0) - ; + ->Field("ShowVisualization", &OcclusionCullingPlaneComponentConfig::m_showVisualization) + ->Field("TransparentVisualization", &OcclusionCullingPlaneComponentConfig::m_transparentVisualization) + ; } } @@ -98,6 +100,10 @@ namespace AZ // add this occlusion plane to the feature processor const AZ::Transform& transform = m_transformInterface->GetWorldTM(); m_handle = m_featureProcessor->AddOcclusionCullingPlane(transform); + + // set visualization + m_featureProcessor->ShowVisualization(m_handle, m_configuration.m_showVisualization); + m_featureProcessor->SetTransparentVisualization(m_handle, m_configuration.m_transparentVisualization); } void OcclusionCullingPlaneComponentController::Deactivate() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.h index 5f0be5315f..2d977a2cf3 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/OcclusionCullingPlaneComponentController.h @@ -32,6 +32,9 @@ namespace AZ AZ_CLASS_ALLOCATOR(OcclusionCullingPlaneComponentConfig, SystemAllocator, 0); static void Reflect(AZ::ReflectContext* context); + bool m_showVisualization = true; + bool m_transparentVisualization = false; + OcclusionCullingPlaneComponentConfig() = default; };