in Gems/Umbra/Code/Source/UmbraSceneComponent/UmbraSceneComponentController.cpp [433:514]
bool UmbraSceneComponentController::UmbraOcclusionView::Update(
const AZ::Vector3& cameraWorldPos, const AZ::Matrix4x4& cameraWorldToClip)
{
AZ_Assert(m_controller.IsSceneReady(), "Umbra scene component controller and assets must be valid and ready before query.");
AZ_Assert(m_query, "Umbra query object must be valid before query.");
AZ_Assert(m_objectIndexList, "Umbra object index list must be valid before query.");
AZ_Assert(m_occlusionBuffer, "Umbra occlusion buffer must be instantiated before query.");
// Reset the object index list and occlusion buffer
m_objectIndexList->setSize(0);
m_occlusionBuffer->clear();
if (m_debugRenderer)
{
m_debugRenderer->m_debugLines.clear();
m_debugRenderer->m_debugStats.clear();
}
// Convert the incoming camera transform into an umbra camera transform
Umbra::Matrix4x4 worldToClip = {};
cameraWorldToClip.StoreToRowMajorFloat16(reinterpret_cast<float*>(worldToClip.m));
// Flip z-axis due to reverse Z perspective transform to get depth range [0,1]
worldToClip.m[2][0] = -worldToClip.m[2][0] + worldToClip.m[3][0];
worldToClip.m[2][1] = -worldToClip.m[2][1] + worldToClip.m[3][1];
worldToClip.m[2][2] = -worldToClip.m[2][2] + worldToClip.m[3][2];
worldToClip.m[2][3] = -worldToClip.m[2][3] + worldToClip.m[3][3];
Umbra::Vector3 cameraPos = {};
cameraWorldPos.StoreToFloat3(cameraPos.v);
Umbra::CameraTransform camera(worldToClip, cameraPos, Umbra::CameraTransform::DEPTHRANGE_ZERO_TO_ONE, Umbra::MF_ROW_MAJOR);
// Set up the visibility query parameters to fill in the object index list and occlusion buffer
Umbra::Visibility visibility(m_objectIndexList.get(), m_occlusionBuffer.get());
const auto& configuration = m_controller.m_configuration;
const bool renderDebugInfo = m_debugRenderer && configuration.m_renderDebugInfo && !configuration.m_pauseDebugInfo;
// Configure debug flags for data to be captured during the query
uint32_t flags = 0;
flags |= Umbra::Query::VisibilityQueryFlags::QUERYFLAG_IGNORE_CAMERA_POSITION;
if (renderDebugInfo)
{
flags |= configuration.m_renderDebugBuffers ? Umbra::Query::VisibilityQueryFlags::DEBUGFLAG_VISIBILITY_LINES : 0;
flags |= configuration.m_renderDebugBounds ? Umbra::Query::VisibilityQueryFlags::DEBUGFLAG_OBJECT_BOUNDS : 0;
flags |= configuration.m_renderDebugVolumes ? Umbra::Query::VisibilityQueryFlags::DEBUGFLAG_VISIBLE_VOLUME : 0;
flags |= configuration.m_renderDebugFrustums ? Umbra::Query::VisibilityQueryFlags::DEBUGFLAG_VIEW_FRUSTUM : 0;
flags |= configuration.m_renderDebugStats ? Umbra::Query::VisibilityQueryFlags::DEBUGFLAG_STATISTICS : 0;
}
const Umbra::Query::ErrorCode errorCode = m_query->queryPortalVisibility(flags, visibility, camera);
if (errorCode != Umbra::Query::ErrorCode::ERROR_OK)
{
Internal::PrintQueryErrorMessage(errorCode);
}
// Store a container of entity IDs corresponding to visible object indices.
m_visibleEntityIds.clear();
const int32_t objectIndexListSize = m_objectIndexList->getSize();
const int32_t* objectIndexListPtr = m_objectIndexList->getPtr();
m_visibleEntityIds.clear();
m_visibleEntityIds.reserve(objectIndexListSize);
for (int32_t i = 0; i < objectIndexListSize; ++i)
{
const int32_t objectIndex = objectIndexListPtr[i];
if (m_controller.m_objectIndexToEntityIdTable.size() > objectIndex)
{
m_visibleEntityIds.insert(m_controller.m_objectIndexToEntityIdTable[objectIndex]);
}
}
// Add any recorded data for debug lines and stats to the accumulated sets
if (renderDebugInfo)
{
AZStd::scoped_lock<decltype(m_controller.m_debugMutex)> lock(m_controller.m_debugMutex);
m_controller.m_debugLines.insert(m_debugRenderer->m_debugLines.begin(), m_debugRenderer->m_debugLines.end());
m_controller.m_debugStats.insert(m_debugRenderer->m_debugStats.begin(), m_debugRenderer->m_debugStats.end());
}
return errorCode == Umbra::Query::ERROR_OK;
}