Stabilize visible render item sorting
This commit is contained in:
@@ -27,6 +27,10 @@ void AppendRenderItemsForGameObject(
|
|||||||
const Math::Vector3& cameraPosition,
|
const Math::Vector3& cameraPosition,
|
||||||
std::vector<VisibleRenderItem>& outVisibleItems);
|
std::vector<VisibleRenderItem>& outVisibleItems);
|
||||||
|
|
||||||
|
bool CompareVisibleRenderItemsStable(
|
||||||
|
const VisibleRenderItem& lhs,
|
||||||
|
const VisibleRenderItem& rhs);
|
||||||
|
|
||||||
std::vector<VisibleRenderItem> CollectRenderItemsForEntityIds(
|
std::vector<VisibleRenderItem> CollectRenderItemsForEntityIds(
|
||||||
const Components::Scene& scene,
|
const Components::Scene& scene,
|
||||||
const std::vector<uint64_t>& entityIds,
|
const std::vector<uint64_t>& entityIds,
|
||||||
|
|||||||
@@ -113,22 +113,7 @@ uint32_t GetAdditionalLightTypeRank(const Components::LightComponent& light) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CompareVisibleItems(const VisibleRenderItem& lhs, const VisibleRenderItem& rhs) {
|
bool CompareVisibleItems(const VisibleRenderItem& lhs, const VisibleRenderItem& rhs) {
|
||||||
if (lhs.renderQueue != rhs.renderQueue) {
|
return CompareVisibleRenderItemsStable(lhs, rhs);
|
||||||
return lhs.renderQueue < rhs.renderQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool isTransparentQueue = IsTransparentRenderQueue(lhs.renderQueue);
|
|
||||||
if (lhs.cameraDistanceSq != rhs.cameraDistanceSq) {
|
|
||||||
return isTransparentQueue
|
|
||||||
? lhs.cameraDistanceSq > rhs.cameraDistanceSq
|
|
||||||
: lhs.cameraDistanceSq < rhs.cameraDistanceSq;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhs.gameObject != rhs.gameObject) {
|
|
||||||
return lhs.gameObject < rhs.gameObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lhs.sectionIndex < rhs.sectionIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -116,6 +116,41 @@ void AppendRenderItemsForGameObject(
|
|||||||
outVisibleItems.push_back(visibleItem);
|
outVisibleItems.push_back(visibleItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CompareVisibleRenderItemsStable(
|
||||||
|
const VisibleRenderItem& lhs,
|
||||||
|
const VisibleRenderItem& rhs) {
|
||||||
|
if (lhs.renderQueue != rhs.renderQueue) {
|
||||||
|
return lhs.renderQueue < rhs.renderQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isTransparentQueue = IsTransparentRenderQueue(lhs.renderQueue);
|
||||||
|
if (lhs.cameraDistanceSq != rhs.cameraDistanceSq) {
|
||||||
|
return isTransparentQueue
|
||||||
|
? lhs.cameraDistanceSq > rhs.cameraDistanceSq
|
||||||
|
: lhs.cameraDistanceSq < rhs.cameraDistanceSq;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Core::uint64 lhsObjectId = lhs.gameObject != nullptr ? lhs.gameObject->GetID() : 0u;
|
||||||
|
const Core::uint64 rhsObjectId = rhs.gameObject != nullptr ? rhs.gameObject->GetID() : 0u;
|
||||||
|
if (lhsObjectId != rhsObjectId) {
|
||||||
|
return lhsObjectId < rhsObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs.hasSection != rhs.hasSection) {
|
||||||
|
return lhs.hasSection && !rhs.hasSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs.sectionIndex != rhs.sectionIndex) {
|
||||||
|
return lhs.sectionIndex < rhs.sectionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs.materialIndex != rhs.materialIndex) {
|
||||||
|
return lhs.materialIndex < rhs.materialIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<VisibleRenderItem> CollectRenderItemsForEntityIds(
|
std::vector<VisibleRenderItem> CollectRenderItemsForEntityIds(
|
||||||
const Components::Scene& scene,
|
const Components::Scene& scene,
|
||||||
const std::vector<uint64_t>& entityIds,
|
const std::vector<uint64_t>& entityIds,
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -24,7 +26,9 @@ using XCEngine::Components::Scene;
|
|||||||
using XCEngine::Math::Matrix4x4;
|
using XCEngine::Math::Matrix4x4;
|
||||||
using XCEngine::Math::Vector3;
|
using XCEngine::Math::Vector3;
|
||||||
using XCEngine::Rendering::BuildRenderCameraData;
|
using XCEngine::Rendering::BuildRenderCameraData;
|
||||||
|
using XCEngine::Rendering::CompareVisibleRenderItemsStable;
|
||||||
using XCEngine::Rendering::CollectRenderItemsForEntityIds;
|
using XCEngine::Rendering::CollectRenderItemsForEntityIds;
|
||||||
|
using XCEngine::Rendering::VisibleRenderItem;
|
||||||
using XCEngine::Resources::Mesh;
|
using XCEngine::Resources::Mesh;
|
||||||
using XCEngine::Resources::MeshSection;
|
using XCEngine::Resources::MeshSection;
|
||||||
using XCEngine::Resources::StaticMeshVertex;
|
using XCEngine::Resources::StaticMeshVertex;
|
||||||
@@ -211,4 +215,33 @@ TEST_F(RenderSceneUtilityTest, CollectRenderItemsForEntityIdsExpandsMeshSections
|
|||||||
EXPECT_EQ(renderables[1].materialIndex, 1u);
|
EXPECT_EQ(renderables[1].materialIndex, 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RenderSceneUtilityStandaloneTest, CompareVisibleRenderItemsUsesStableObjectIdOrdering) {
|
||||||
|
using Storage = std::aligned_storage_t<sizeof(GameObject), alignof(GameObject)>;
|
||||||
|
|
||||||
|
Storage storage[2];
|
||||||
|
GameObject* lowerIdHigherAddress = new (&storage[1]) GameObject("LowerId");
|
||||||
|
GameObject* higherIdLowerAddress = new (&storage[0]) GameObject("HigherId");
|
||||||
|
|
||||||
|
ASSERT_LT(lowerIdHigherAddress->GetID(), higherIdLowerAddress->GetID());
|
||||||
|
ASSERT_GT(
|
||||||
|
reinterpret_cast<uintptr_t>(lowerIdHigherAddress),
|
||||||
|
reinterpret_cast<uintptr_t>(higherIdLowerAddress));
|
||||||
|
|
||||||
|
VisibleRenderItem lhs = {};
|
||||||
|
lhs.gameObject = lowerIdHigherAddress;
|
||||||
|
lhs.renderQueue = 2000;
|
||||||
|
lhs.cameraDistanceSq = 9.0f;
|
||||||
|
|
||||||
|
VisibleRenderItem rhs = {};
|
||||||
|
rhs.gameObject = higherIdLowerAddress;
|
||||||
|
rhs.renderQueue = 2000;
|
||||||
|
rhs.cameraDistanceSq = 9.0f;
|
||||||
|
|
||||||
|
EXPECT_TRUE(CompareVisibleRenderItemsStable(lhs, rhs));
|
||||||
|
EXPECT_FALSE(CompareVisibleRenderItemsStable(rhs, lhs));
|
||||||
|
|
||||||
|
higherIdLowerAddress->~GameObject();
|
||||||
|
lowerIdHigherAddress->~GameObject();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user