#pragma once #include #include #include "engine/Runtime/Rendering/FrameData/RenderSceneData.h" #include #include #include namespace XCEngine { namespace Rendering { inline FilteringSettings BuildDefaultFilteringSettings(RendererListType type) { FilteringSettings filtering = {}; switch (type) { case RendererListType::AllVisible: break; case RendererListType::Opaque: filtering.renderQueueMax = static_cast(Resources::MaterialRenderQueue::Transparent) - 1; break; case RendererListType::Transparent: filtering.renderQueueMin = static_cast(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& visibleItems) { RendererList rendererList = {}; rendererList.desc = BuildDefaultRendererListDesc(type); rendererList.visibleRenderItemIndices.reserve(visibleItems.size()); for (Core::uint32 visibleItemIndex = 0; visibleItemIndex < static_cast(visibleItems.size()); ++visibleItemIndex) { if (!MatchesRendererListDesc( visibleItems[visibleItemIndex], rendererList.desc)) { continue; } rendererList.visibleRenderItemIndices.push_back(visibleItemIndex); } return rendererList; } template 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 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)); return; } std::vector 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