Stabilize 3DGS D3D12 phase 3 and sort key setup

This commit is contained in:
2026-04-13 02:23:39 +08:00
parent 1d6f2e290d
commit b7428b0ef1
10 changed files with 1281 additions and 33 deletions

View File

@@ -53,6 +53,15 @@ struct RawGaussianSplat {
Float4 rotation = {};
};
struct GaussianPlyPropertyLayout {
const PlyProperty* position[3] = {};
const PlyProperty* dc0[3] = {};
const PlyProperty* opacity = nullptr;
const PlyProperty* scale[3] = {};
const PlyProperty* rotation[4] = {};
std::array<const PlyProperty*, GaussianSplatRuntimeData::kShCoefficientCount * 3> sh = {};
};
std::string TrimTrailingCarriageReturn(std::string line) {
if (!line.empty() && line.back() == '\r') {
line.pop_back();
@@ -243,6 +252,39 @@ bool RequireProperty(
return true;
}
bool BuildGaussianPlyPropertyLayout(
const std::unordered_map<std::string_view, const PlyProperty*>& propertyMap,
GaussianPlyPropertyLayout& outLayout,
std::string& outErrorMessage) {
outLayout = {};
if (!RequireProperty(propertyMap, "x", outLayout.position[0], outErrorMessage) ||
!RequireProperty(propertyMap, "y", outLayout.position[1], outErrorMessage) ||
!RequireProperty(propertyMap, "z", outLayout.position[2], outErrorMessage) ||
!RequireProperty(propertyMap, "f_dc_0", outLayout.dc0[0], outErrorMessage) ||
!RequireProperty(propertyMap, "f_dc_1", outLayout.dc0[1], outErrorMessage) ||
!RequireProperty(propertyMap, "f_dc_2", outLayout.dc0[2], outErrorMessage) ||
!RequireProperty(propertyMap, "opacity", outLayout.opacity, outErrorMessage) ||
!RequireProperty(propertyMap, "scale_0", outLayout.scale[0], outErrorMessage) ||
!RequireProperty(propertyMap, "scale_1", outLayout.scale[1], outErrorMessage) ||
!RequireProperty(propertyMap, "scale_2", outLayout.scale[2], outErrorMessage) ||
!RequireProperty(propertyMap, "rot_0", outLayout.rotation[0], outErrorMessage) ||
!RequireProperty(propertyMap, "rot_1", outLayout.rotation[1], outErrorMessage) ||
!RequireProperty(propertyMap, "rot_2", outLayout.rotation[2], outErrorMessage) ||
!RequireProperty(propertyMap, "rot_3", outLayout.rotation[3], outErrorMessage)) {
return false;
}
for (uint32_t index = 0; index < outLayout.sh.size(); ++index) {
const std::string propertyName = "f_rest_" + std::to_string(index);
if (!RequireProperty(propertyMap, propertyName, outLayout.sh[index], outErrorMessage)) {
return false;
}
}
return true;
}
Float3 Min(const Float3& a, const Float3& b) {
return {
std::min(a.x, b.x),
@@ -390,32 +432,31 @@ void WriteFloat4(std::vector<std::byte>& bytes, size_t offset, float x, float y,
bool ReadGaussianSplat(
const std::byte* vertexBytes,
const std::unordered_map<std::string_view, const PlyProperty*>& propertyMap,
const GaussianPlyPropertyLayout& propertyLayout,
RawGaussianSplat& outSplat,
std::string& outErrorMessage) {
const PlyProperty* property = nullptr;
auto readFloat = [&](std::string_view name, float& outValue) -> bool {
if (!RequireProperty(propertyMap, name, property, outErrorMessage)) {
auto readFloat = [&](const PlyProperty* property, float& outValue) -> bool {
if (property == nullptr) {
outErrorMessage = "Gaussian PLY property layout is incomplete.";
return false;
}
return ReadPropertyAsFloat(vertexBytes, *property, outValue);
};
if (!readFloat("x", outSplat.position.x) ||
!readFloat("y", outSplat.position.y) ||
!readFloat("z", outSplat.position.z) ||
!readFloat("f_dc_0", outSplat.dc0.x) ||
!readFloat("f_dc_1", outSplat.dc0.y) ||
!readFloat("f_dc_2", outSplat.dc0.z) ||
!readFloat("opacity", outSplat.opacity) ||
!readFloat("scale_0", outSplat.scale.x) ||
!readFloat("scale_1", outSplat.scale.y) ||
!readFloat("scale_2", outSplat.scale.z) ||
!readFloat("rot_0", outSplat.rotation.x) ||
!readFloat("rot_1", outSplat.rotation.y) ||
!readFloat("rot_2", outSplat.rotation.z) ||
!readFloat("rot_3", outSplat.rotation.w)) {
if (!readFloat(propertyLayout.position[0], outSplat.position.x) ||
!readFloat(propertyLayout.position[1], outSplat.position.y) ||
!readFloat(propertyLayout.position[2], outSplat.position.z) ||
!readFloat(propertyLayout.dc0[0], outSplat.dc0.x) ||
!readFloat(propertyLayout.dc0[1], outSplat.dc0.y) ||
!readFloat(propertyLayout.dc0[2], outSplat.dc0.z) ||
!readFloat(propertyLayout.opacity, outSplat.opacity) ||
!readFloat(propertyLayout.scale[0], outSplat.scale.x) ||
!readFloat(propertyLayout.scale[1], outSplat.scale.y) ||
!readFloat(propertyLayout.scale[2], outSplat.scale.z) ||
!readFloat(propertyLayout.rotation[0], outSplat.rotation.x) ||
!readFloat(propertyLayout.rotation[1], outSplat.rotation.y) ||
!readFloat(propertyLayout.rotation[2], outSplat.rotation.z) ||
!readFloat(propertyLayout.rotation[3], outSplat.rotation.w)) {
if (outErrorMessage.empty()) {
outErrorMessage = "Failed to read required Gaussian splat PLY properties.";
}
@@ -424,8 +465,7 @@ bool ReadGaussianSplat(
std::array<float, GaussianSplatRuntimeData::kShCoefficientCount * 3> shRaw = {};
for (uint32_t index = 0; index < shRaw.size(); ++index) {
const std::string propertyName = "f_rest_" + std::to_string(index);
if (!readFloat(propertyName, shRaw[index])) {
if (!readFloat(propertyLayout.sh[index], shRaw[index])) {
if (outErrorMessage.empty()) {
outErrorMessage = "Failed to read SH rest coefficients from PLY.";
}
@@ -478,6 +518,11 @@ bool LoadGaussianSceneFromPly(
return false;
}
GaussianPlyPropertyLayout propertyLayout;
if (!BuildGaussianPlyPropertyLayout(propertyMap, propertyLayout, outErrorMessage)) {
return false;
}
outData.splatCount = header.vertexCount;
outData.colorTextureWidth = GaussianSplatRuntimeData::kColorTextureWidth;
outData.colorTextureHeight =
@@ -513,7 +558,7 @@ bool LoadGaussianSceneFromPly(
}
RawGaussianSplat splat;
if (!ReadGaussianSplat(vertexBytes.data(), propertyMap, splat, outErrorMessage)) {
if (!ReadGaussianSplat(vertexBytes.data(), propertyLayout, splat, outErrorMessage)) {
return false;
}