220 lines
6.5 KiB
C++
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
|