Cached occlusion plane corner points and AABB in the feature processor
This commit is contained in:
+44
-5
@@ -33,6 +33,7 @@ namespace AZ
|
||||
void OcclusionCullingPlaneFeatureProcessor::Activate()
|
||||
{
|
||||
m_occlusionCullingPlanes.reserve(InitialOcclusionCullingPlanesAllocationSize);
|
||||
m_rpiOcclusionPlanes.reserve(InitialOcclusionCullingPlanesAllocationSize);
|
||||
|
||||
EnableSceneNotification();
|
||||
}
|
||||
@@ -48,13 +49,46 @@ namespace AZ
|
||||
}
|
||||
|
||||
void OcclusionCullingPlaneFeatureProcessor::OnBeginPrepareRender()
|
||||
{
|
||||
AZStd::vector<AZ::Transform> occlusionCullingPlanes;
|
||||
for (auto& occlusionCullingPlane : m_occlusionCullingPlanes)
|
||||
{
|
||||
if (m_rpiListNeedsUpdate)
|
||||
{
|
||||
occlusionCullingPlanes.push_back(occlusionCullingPlane->GetTransform());
|
||||
// rebuild the RPI occlusion list
|
||||
m_rpiOcclusionPlanes.clear();
|
||||
|
||||
for (auto& occlusionCullingPlane : m_occlusionCullingPlanes)
|
||||
{
|
||||
if (!occlusionCullingPlane->GetEnabled())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RPI::CullingScene::OcclusionPlane rpiOcclusionPlane;
|
||||
|
||||
static const Vector3 BL = Vector3(-0.5f, -0.5f, 0.0f);
|
||||
static const Vector3 BR = Vector3(0.5f, -0.5f, 0.0f);
|
||||
static const Vector3 TL = Vector3(-0.5f, 0.5f, 0.0f);
|
||||
static const Vector3 TR = Vector3(0.5f, 0.5f, 0.0f);
|
||||
|
||||
const AZ::Transform& transform = occlusionCullingPlane->GetTransform();
|
||||
|
||||
// convert corners to world space
|
||||
rpiOcclusionPlane.m_cornerBL = transform.TransformPoint(BL);
|
||||
rpiOcclusionPlane.m_cornerBR = transform.TransformPoint(BR);
|
||||
rpiOcclusionPlane.m_cornerTL = transform.TransformPoint(TL);
|
||||
rpiOcclusionPlane.m_cornerTR = transform.TransformPoint(TR);
|
||||
|
||||
// build world space AABB
|
||||
AZ::Vector3 aabbMin = rpiOcclusionPlane.m_cornerBL.GetMin(rpiOcclusionPlane.m_cornerTR);
|
||||
AZ::Vector3 aabbMax = rpiOcclusionPlane.m_cornerBL.GetMax(rpiOcclusionPlane.m_cornerTR);
|
||||
rpiOcclusionPlane.m_aabb = Aabb::CreateFromMinMax(aabbMin, aabbMax);
|
||||
|
||||
m_rpiOcclusionPlanes.push_back(rpiOcclusionPlane);
|
||||
}
|
||||
|
||||
GetParentScene()->GetCullingScene()->SetOcclusionPlanes(m_rpiOcclusionPlanes);
|
||||
|
||||
m_rpiListNeedsUpdate = false;
|
||||
}
|
||||
GetParentScene()->GetCullingScene()->SetOcclusionCullingPlanes(occlusionCullingPlanes);
|
||||
}
|
||||
|
||||
OcclusionCullingPlaneHandle OcclusionCullingPlaneFeatureProcessor::AddOcclusionCullingPlane(const AZ::Transform& transform)
|
||||
@@ -63,6 +97,8 @@ namespace AZ
|
||||
occlusionCullingPlane->Init(GetParentScene());
|
||||
occlusionCullingPlane->SetTransform(transform);
|
||||
m_occlusionCullingPlanes.push_back(occlusionCullingPlane);
|
||||
m_rpiListNeedsUpdate = true;
|
||||
|
||||
return occlusionCullingPlane;
|
||||
}
|
||||
|
||||
@@ -78,18 +114,21 @@ namespace AZ
|
||||
AZ_Assert(itEntry != m_occlusionCullingPlanes.end(), "RemoveOcclusionCullingPlane called with an occlusion plane that is not in the occlusion plane list");
|
||||
m_occlusionCullingPlanes.erase(itEntry);
|
||||
occlusionCullingPlane = nullptr;
|
||||
m_rpiListNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void OcclusionCullingPlaneFeatureProcessor::SetTransform(const OcclusionCullingPlaneHandle& occlusionCullingPlane, const AZ::Transform& transform)
|
||||
{
|
||||
AZ_Assert(occlusionCullingPlane.get(), "SetTransform called with an invalid handle");
|
||||
occlusionCullingPlane->SetTransform(transform);
|
||||
m_rpiListNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void OcclusionCullingPlaneFeatureProcessor::SetEnabled(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool enabled)
|
||||
{
|
||||
AZ_Assert(occlusionCullingPlane.get(), "Enable called with an invalid handle");
|
||||
occlusionCullingPlane->SetEnabled(enabled);
|
||||
m_rpiListNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void OcclusionCullingPlaneFeatureProcessor::ShowVisualization(const OcclusionCullingPlaneHandle& occlusionCullingPlane, bool showVisualization)
|
||||
|
||||
+4
@@ -57,6 +57,10 @@ namespace AZ
|
||||
// list of occlusion planes
|
||||
const size_t InitialOcclusionCullingPlanesAllocationSize = 64;
|
||||
OcclusionCullingPlaneVector m_occlusionCullingPlanes;
|
||||
|
||||
// prebuilt list of RPI scene occlusion planes
|
||||
RPI::CullingScene::OcclusionPlaneVector m_rpiOcclusionPlanes;
|
||||
bool m_rpiListNeedsUpdate = false;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -215,8 +215,20 @@ namespace AZ
|
||||
void Activate(const class Scene* parentScene);
|
||||
void Deactivate();
|
||||
|
||||
struct OcclusionPlane
|
||||
{
|
||||
// World space corners of the occluson plane
|
||||
Vector3 m_cornerBL;
|
||||
Vector3 m_cornerBR;
|
||||
Vector3 m_cornerTL;
|
||||
Vector3 m_cornerTR;
|
||||
|
||||
Aabb m_aabb;
|
||||
};
|
||||
using OcclusionPlaneVector = AZStd::vector<OcclusionPlane>;
|
||||
|
||||
//! Sets a list of occlusion planes to be used during the culling process.
|
||||
void SetOcclusionCullingPlanes(const AZStd::vector<AZ::Transform>& occlusionCullingPlanes) { m_occlusionCullingPlanes = occlusionCullingPlanes; }
|
||||
void SetOcclusionPlanes(const OcclusionPlaneVector& occlusionPlanes) { m_occlusionPlanes = occlusionPlanes; }
|
||||
|
||||
//! Notifies the CullingScene that culling will begin for this frame.
|
||||
void BeginCulling(const AZStd::vector<ViewPtr>& views);
|
||||
@@ -258,7 +270,7 @@ namespace AZ
|
||||
AzFramework::IVisibilityScene* m_visScene = nullptr;
|
||||
CullingDebugContext m_debugCtx;
|
||||
AZStd::concurrency_checker m_cullDataConcurrencyCheck;
|
||||
AZStd::vector<AZ::Transform> m_occlusionCullingPlanes;
|
||||
OcclusionPlaneVector m_occlusionPlanes;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -546,60 +546,37 @@ namespace AZ
|
||||
|
||||
#if AZ_TRAIT_MASKED_OCCLUSION_CULLING_SUPPORTED
|
||||
// setup occlusion culling, if necessary
|
||||
MaskedOcclusionCulling* maskedOcclusionCulling = m_occlusionCullingPlanes.empty() ? nullptr : view.GetMaskedOcclusionCulling();
|
||||
MaskedOcclusionCulling* maskedOcclusionCulling = m_occlusionPlanes.empty() ? nullptr : view.GetMaskedOcclusionCulling();
|
||||
if (maskedOcclusionCulling)
|
||||
{
|
||||
// frustum cull occlusion planes
|
||||
using OccluderEntry = AZStd::pair<AZ::Transform, float>;
|
||||
AZStd::vector<OccluderEntry> visibleOccluders;
|
||||
for (const AZ::Transform& transform : m_occlusionCullingPlanes)
|
||||
using VisibleOcclusionPlane = AZStd::pair<OcclusionPlane, float>;
|
||||
AZStd::vector<VisibleOcclusionPlane> visibleOccluders;
|
||||
for (const auto& occlusionPlane : m_occlusionPlanes)
|
||||
{
|
||||
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))
|
||||
if (ShapeIntersection::Overlaps(frustum, occlusionPlane.m_aabb))
|
||||
{
|
||||
// occluder is visible, compute view space distance and add to list
|
||||
float depth = (view.GetWorldToViewMatrix() * occluderAabb.GetMin()).GetZ();
|
||||
depth = AZStd::min(depth, (view.GetWorldToViewMatrix() * occluderAabb.GetMax()).GetZ());
|
||||
float depth = (view.GetWorldToViewMatrix() * occlusionPlane.m_aabb.GetMin()).GetZ();
|
||||
depth = AZStd::min(depth, (view.GetWorldToViewMatrix() * occlusionPlane.m_aabb.GetMax()).GetZ());
|
||||
|
||||
visibleOccluders.push_back(AZStd::make_pair(transform, depth));
|
||||
visibleOccluders.push_back(AZStd::make_pair(occlusionPlane, depth));
|
||||
}
|
||||
}
|
||||
|
||||
// sort the occlusion planes by view space distance, front-to-back
|
||||
AZStd::sort(visibleOccluders.begin(), visibleOccluders.end(), [](const OccluderEntry& LHS, const OccluderEntry& RHS)
|
||||
AZStd::sort(visibleOccluders.begin(), visibleOccluders.end(), [](const VisibleOcclusionPlane& LHS, const VisibleOcclusionPlane& RHS)
|
||||
{
|
||||
return LHS.second > RHS.second;
|
||||
});
|
||||
|
||||
for (const OccluderEntry& occluder : visibleOccluders)
|
||||
for (const VisibleOcclusionPlane& occlusionPlane: visibleOccluders)
|
||||
{
|
||||
const AZ::Transform& transform = occluder.first;
|
||||
|
||||
// find the corners of the plane
|
||||
static const Vector3 BL = Vector3(-0.5f, -0.5f, 0.0f);
|
||||
static const Vector3 BR = Vector3(0.5f, -0.5f, 0.0f);
|
||||
static const Vector3 TL = Vector3(-0.5f, 0.5f, 0.0f);
|
||||
static const Vector3 TR = Vector3(0.5f, 0.5f, 0.0f);
|
||||
|
||||
Vector3 planeBL = transform.TransformPoint(BL);
|
||||
Vector3 planeBR = transform.TransformPoint(BR);
|
||||
Vector3 planeTL = transform.TransformPoint(TL);
|
||||
Vector3 planeTR = transform.TransformPoint(TR);
|
||||
|
||||
// convert to clip-space
|
||||
Vector4 projectedBL = view.GetWorldToClipMatrix() * Vector4(planeBL);
|
||||
Vector4 projectedBR = view.GetWorldToClipMatrix() * Vector4(planeBR);
|
||||
Vector4 projectedTL = view.GetWorldToClipMatrix() * Vector4(planeTL);
|
||||
Vector4 projectedTR = view.GetWorldToClipMatrix() * Vector4(planeTR);
|
||||
Vector4 projectedBL = view.GetWorldToClipMatrix() * Vector4(occlusionPlane.first.m_cornerBL);
|
||||
Vector4 projectedBR = view.GetWorldToClipMatrix() * Vector4(occlusionPlane.first.m_cornerBR);
|
||||
Vector4 projectedTL = view.GetWorldToClipMatrix() * Vector4(occlusionPlane.first.m_cornerTL);
|
||||
Vector4 projectedTR = view.GetWorldToClipMatrix() * Vector4(occlusionPlane.first.m_cornerTR);
|
||||
|
||||
// store to float array
|
||||
float verts[16];
|
||||
|
||||
Reference in New Issue
Block a user