Cull invisible gaussian splat chunks in prepare pass

This commit is contained in:
2026-04-11 14:22:51 +08:00
parent c543ccf79c
commit 2fb6eca854
3 changed files with 177 additions and 2 deletions

View File

@@ -50,6 +50,53 @@ constexpr uint32_t kFrameWidth = 1280;
constexpr uint32_t kFrameHeight = 720;
constexpr uint32_t kBaselineSubsetSplatCount = 65536u;
XCEngine::Core::uint16 FloatToHalfBits(float value) {
uint32_t bits = 0u;
std::memcpy(&bits, &value, sizeof(bits));
const uint32_t sign = (bits >> 16u) & 0x8000u;
uint32_t mantissa = bits & 0x007fffffu;
int32_t exponent = static_cast<int32_t>((bits >> 23u) & 0xffu) - 127 + 15;
if (exponent <= 0) {
if (exponent < -10) {
return static_cast<XCEngine::Core::uint16>(sign);
}
mantissa = (mantissa | 0x00800000u) >> static_cast<uint32_t>(1 - exponent);
if ((mantissa & 0x00001000u) != 0u) {
mantissa += 0x00002000u;
}
return static_cast<XCEngine::Core::uint16>(sign | (mantissa >> 13u));
}
if (exponent >= 31) {
return static_cast<XCEngine::Core::uint16>(sign | 0x7c00u);
}
if ((mantissa & 0x00001000u) != 0u) {
mantissa += 0x00002000u;
if ((mantissa & 0x00800000u) != 0u) {
mantissa = 0u;
++exponent;
if (exponent >= 31) {
return static_cast<XCEngine::Core::uint16>(sign | 0x7c00u);
}
}
}
return static_cast<XCEngine::Core::uint16>(
sign |
(static_cast<uint32_t>(exponent) << 10u) |
(mantissa >> 13u));
}
uint32_t PackHalfRange(float minValue, float maxValue) {
return static_cast<uint32_t>(FloatToHalfBits(minValue)) |
(static_cast<uint32_t>(FloatToHalfBits(maxValue)) << 16u);
}
std::filesystem::path GetRoomPlyPath() {
return std::filesystem::path(XCENGINE_TEST_ROOM_PLY_PATH);
}
@@ -153,21 +200,39 @@ GaussianSplat* CreateGaussianSplatSubset(
-std::numeric_limits<float>::max(),
-std::numeric_limits<float>::max(),
-std::numeric_limits<float>::max());
Vector3 minScale(
std::numeric_limits<float>::max(),
std::numeric_limits<float>::max(),
std::numeric_limits<float>::max());
Vector3 maxScale(
-std::numeric_limits<float>::max(),
-std::numeric_limits<float>::max(),
-std::numeric_limits<float>::max());
for (uint32_t subsetIndex = startIndex; subsetIndex < endIndex; ++subsetIndex) {
const Vector3& position = subsetPositions[subsetIndex].position;
const Vector3& scale = subsetOther[subsetIndex].scale;
minPosition.x = std::min(minPosition.x, position.x);
minPosition.y = std::min(minPosition.y, position.y);
minPosition.z = std::min(minPosition.z, position.z);
maxPosition.x = std::max(maxPosition.x, position.x);
maxPosition.y = std::max(maxPosition.y, position.y);
maxPosition.z = std::max(maxPosition.z, position.z);
minScale.x = std::min(minScale.x, scale.x);
minScale.y = std::min(minScale.y, scale.y);
minScale.z = std::min(minScale.z, scale.z);
maxScale.x = std::max(maxScale.x, scale.x);
maxScale.y = std::max(maxScale.y, scale.y);
maxScale.z = std::max(maxScale.z, scale.z);
}
GaussianSplatChunkRecord chunk = {};
chunk.posX = Vector2(minPosition.x, maxPosition.x);
chunk.posY = Vector2(minPosition.y, maxPosition.y);
chunk.posZ = Vector2(minPosition.z, maxPosition.z);
chunk.sclX = PackHalfRange(minScale.x, maxScale.x);
chunk.sclY = PackHalfRange(minScale.y, maxScale.y);
chunk.sclZ = PackHalfRange(minScale.z, maxScale.z);
subsetChunks[chunkIndex] = chunk;
}