Files
XCEngine/engine/Runtime/Rendering/FrameData/RendererListUtils.h

220 lines
6.5 KiB
C++

#pragma once
#include <XCEngine/Components/MeshRendererComponent.h>
#include <XCEngine/Resources/Material/Material.h>
#include "engine/Runtime/Rendering/FrameData/RenderSceneData.h"
#include <algorithm>
#include <utility>
#include <vector>
namespace XCEngine {
namespace Rendering {
inline FilteringSettings BuildDefaultFilteringSettings(RendererListType type) {
FilteringSettings filtering = {};
switch (type) {
case RendererListType::AllVisible:
break;
case RendererListType::Opaque:
filtering.renderQueueMax =
static_cast<Core::int32>(Resources::MaterialRenderQueue::Transparent) - 1;
break;
case RendererListType::Transparent:
filtering.renderQueueMin =
static_cast<Core::int32>(Resources::MaterialRenderQueue::Transparent);
break;
case RendererListType::ShadowCaster:
filtering.requireShadowCasting = true;
break;
case RendererListType::ObjectId:
filtering.requireRenderObjectId = true;
break;
}
return filtering;
}
inline SortingSettings BuildDefaultSortingSettings(RendererListType type) {
SortingSettings sorting = {};
switch (type) {
case RendererListType::Opaque:
case RendererListType::ShadowCaster:
case RendererListType::ObjectId:
sorting.sortMode = RendererSortMode::FrontToBack;
break;
case RendererListType::Transparent:
sorting.sortMode = RendererSortMode::BackToFront;
break;
case RendererListType::AllVisible:
sorting.sortMode = RendererSortMode::None;
break;
}
return sorting;
}
inline RendererListDesc BuildDefaultRendererListDesc(RendererListType type) {
RendererListDesc desc = {};
desc.type = type;
desc.filtering = BuildDefaultFilteringSettings(type);
desc.sorting = BuildDefaultSortingSettings(type);
return desc;
}
inline bool MatchesFilteringSettings(
const VisibleRenderItem& visibleItem,
const FilteringSettings& filtering) {
if (visibleItem.renderQueue < filtering.renderQueueMin ||
visibleItem.renderQueue > filtering.renderQueueMax) {
return false;
}
if (visibleItem.renderLayer >= 32u ||
((filtering.renderLayerMask &
(1u << visibleItem.renderLayer)) == 0u)) {
return false;
}
if (filtering.requireShadowCasting &&
visibleItem.meshRenderer != nullptr &&
!visibleItem.meshRenderer->GetCastShadows()) {
return false;
}
if (filtering.requireRenderObjectId &&
!IsValidRenderObjectId(visibleItem.renderObjectId)) {
return false;
}
return true;
}
inline bool MatchesRendererListDesc(
const VisibleRenderItem& visibleItem,
const RendererListDesc& desc) {
return MatchesFilteringSettings(visibleItem, desc.filtering);
}
inline RendererList BuildRendererList(
RendererListType type,
const std::vector<VisibleRenderItem>& visibleItems) {
RendererList rendererList = {};
rendererList.desc = BuildDefaultRendererListDesc(type);
rendererList.visibleRenderItemIndices.reserve(visibleItems.size());
for (Core::uint32 visibleItemIndex = 0;
visibleItemIndex < static_cast<Core::uint32>(visibleItems.size());
++visibleItemIndex) {
if (!MatchesRendererListDesc(
visibleItems[visibleItemIndex],
rendererList.desc)) {
continue;
}
rendererList.visibleRenderItemIndices.push_back(visibleItemIndex);
}
return rendererList;
}
template <typename Visitor>
inline void VisitRendererListVisibleItems(
const RenderSceneData& sceneData,
RendererListType rendererListType,
Visitor&& visitor) {
const RendererList* rendererList = sceneData.FindRendererList(rendererListType);
if (rendererList != nullptr) {
for (Core::uint32 visibleItemIndex : rendererList->visibleRenderItemIndices) {
const VisibleRenderItem* visibleItem =
sceneData.TryGetVisibleRenderItem(visibleItemIndex);
if (visibleItem == nullptr) {
continue;
}
visitor(*visibleItem);
}
return;
}
const RendererListDesc fallbackDesc = BuildDefaultRendererListDesc(rendererListType);
for (const VisibleRenderItem& visibleItem : sceneData.visibleItems) {
if (!MatchesRendererListDesc(visibleItem, fallbackDesc)) {
continue;
}
visitor(visibleItem);
}
}
template <typename Visitor>
inline void VisitRendererListVisibleItems(
const RenderSceneData& sceneData,
const RendererListDesc& rendererListDesc,
Visitor&& visitor) {
const RendererListDesc defaultDesc =
BuildDefaultRendererListDesc(
rendererListDesc.type);
if (rendererListDesc == defaultDesc) {
VisitRendererListVisibleItems(
sceneData,
rendererListDesc.type,
std::forward<Visitor>(visitor));
return;
}
std::vector<const VisibleRenderItem*> matchedItems;
matchedItems.reserve(sceneData.visibleItems.size());
for (const VisibleRenderItem& visibleItem : sceneData.visibleItems) {
if (!MatchesRendererListDesc(
visibleItem,
rendererListDesc)) {
continue;
}
matchedItems.push_back(&visibleItem);
}
switch (rendererListDesc.sorting.sortMode) {
case RendererSortMode::FrontToBack:
std::stable_sort(
matchedItems.begin(),
matchedItems.end(),
[](const VisibleRenderItem* lhs, const VisibleRenderItem* rhs) {
return lhs != nullptr &&
rhs != nullptr &&
lhs->cameraDistanceSq <
rhs->cameraDistanceSq;
});
break;
case RendererSortMode::BackToFront:
std::stable_sort(
matchedItems.begin(),
matchedItems.end(),
[](const VisibleRenderItem* lhs, const VisibleRenderItem* rhs) {
return lhs != nullptr &&
rhs != nullptr &&
lhs->cameraDistanceSq >
rhs->cameraDistanceSq;
});
break;
case RendererSortMode::None:
default:
break;
}
for (const VisibleRenderItem* visibleItem : matchedItems) {
if (visibleItem == nullptr) {
continue;
}
visitor(*visibleItem);
}
}
} // namespace Rendering
} // namespace XCEngine