diff --git a/engine/include/XCEngine/Rendering/ObjectIdEncoding.h b/engine/include/XCEngine/Rendering/ObjectIdEncoding.h index af2cc951..b4e1788f 100644 --- a/engine/include/XCEngine/Rendering/ObjectIdEncoding.h +++ b/engine/include/XCEngine/Rendering/ObjectIdEncoding.h @@ -1,18 +1,29 @@ #pragma once +#include #include -#include - namespace XCEngine { namespace Rendering { -inline uint32_t EncodeObjectIdToUInt32(uint64_t objectId) { - return static_cast(objectId & 0xFFFFFFFFull); +using EncodedObjectId = Core::uint32; + +// Object-id render targets store only the low 32 bits of a runtime object id. +// This codec is for editor/runtime picking surfaces, not for persistent ids. +inline bool CanEncodeObjectIdWithoutLoss(Core::uint64 objectId) { + return (objectId & 0xFFFFFFFF00000000ull) == 0ull; } -inline Math::Vector4 EncodeObjectIdToColor(uint64_t objectId) { - const uint32_t encodedId = EncodeObjectIdToUInt32(objectId); +inline EncodedObjectId EncodeObjectIdToEncodedId(Core::uint64 objectId) { + return static_cast(objectId & 0xFFFFFFFFull); +} + +inline EncodedObjectId EncodeObjectIdToUInt32(Core::uint64 objectId) { + return EncodeObjectIdToEncodedId(objectId); +} + +inline Math::Vector4 EncodeObjectIdToColor(Core::uint64 objectId) { + const EncodedObjectId encodedId = EncodeObjectIdToEncodedId(objectId); constexpr float kInv255 = 1.0f / 255.0f; return Math::Vector4( static_cast((encodedId >> 0) & 0xFFu) * kInv255, @@ -21,11 +32,23 @@ inline Math::Vector4 EncodeObjectIdToColor(uint64_t objectId) { static_cast((encodedId >> 24) & 0xFFu) * kInv255); } -inline uint32_t DecodeObjectIdFromColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return static_cast(r) | - (static_cast(g) << 8u) | - (static_cast(b) << 16u) | - (static_cast(a) << 24u); +inline EncodedObjectId DecodeEncodedObjectIdFromColor( + Core::uint8 r, + Core::uint8 g, + Core::uint8 b, + Core::uint8 a) { + return static_cast(r) | + (static_cast(g) << 8u) | + (static_cast(b) << 16u) | + (static_cast(a) << 24u); +} + +inline Core::uint64 DecodeObjectIdFromColor( + Core::uint8 r, + Core::uint8 g, + Core::uint8 b, + Core::uint8 a) { + return static_cast(DecodeEncodedObjectIdFromColor(r, g, b, a)); } } // namespace Rendering diff --git a/tests/Rendering/unit/CMakeLists.txt b/tests/Rendering/unit/CMakeLists.txt index 03f41f9c..9a64b790 100644 --- a/tests/Rendering/unit/CMakeLists.txt +++ b/tests/Rendering/unit/CMakeLists.txt @@ -4,9 +4,8 @@ project(XCEngine_RenderingUnitTests) set(RENDERING_UNIT_TEST_SOURCES test_render_pass.cpp + test_object_id_encoding.cpp test_builtin_forward_pipeline.cpp - test_builtin_post_process_pass_plan.cpp - test_builtin_post_process_pass_sequence_builder.cpp test_camera_scene_renderer.cpp test_scene_render_request_planner.cpp test_scene_render_request_utils.cpp diff --git a/tests/Rendering/unit/test_object_id_encoding.cpp b/tests/Rendering/unit/test_object_id_encoding.cpp new file mode 100644 index 00000000..702f167f --- /dev/null +++ b/tests/Rendering/unit/test_object_id_encoding.cpp @@ -0,0 +1,33 @@ +#include + +#include + +using namespace XCEngine::Rendering; + +TEST(ObjectIdEncoding_Test, EncodesOnlyLow32BitsIntoPickingId) { + constexpr uint64_t objectId = 0x123456789ABCDEF0ull; + + EXPECT_FALSE(CanEncodeObjectIdWithoutLoss(objectId)); + EXPECT_EQ(EncodeObjectIdToEncodedId(objectId), 0x9ABCDEF0u); + EXPECT_EQ(EncodeObjectIdToUInt32(objectId), 0x9ABCDEF0u); +} + +TEST(ObjectIdEncoding_Test, DecodesColorBackToWidenedRuntimeId) { + constexpr uint8_t r = 0x12u; + constexpr uint8_t g = 0x34u; + constexpr uint8_t b = 0x56u; + constexpr uint8_t a = 0x78u; + + EXPECT_EQ(DecodeEncodedObjectIdFromColor(r, g, b, a), 0x78563412u); + EXPECT_EQ(DecodeObjectIdFromColor(r, g, b, a), 0x78563412ull); +} + +TEST(ObjectIdEncoding_Test, EncodesColorChannelsFromLow32Bits) { + const auto encodedColor = EncodeObjectIdToColor(0x78563412ull); + constexpr float kInv255 = 1.0f / 255.0f; + + EXPECT_FLOAT_EQ(encodedColor.x, 0x12u * kInv255); + EXPECT_FLOAT_EQ(encodedColor.y, 0x34u * kInv255); + EXPECT_FLOAT_EQ(encodedColor.z, 0x56u * kInv255); + EXPECT_FLOAT_EQ(encodedColor.w, 0x78u * kInv255); +}