Derive gaussian splat SH order from resource layout

This commit is contained in:
2026-04-11 06:57:47 +08:00
parent 785377bc9b
commit b3acb5afc2
5 changed files with 82 additions and 1 deletions

View File

@@ -43,6 +43,11 @@ enum class GaussianSplatSectionFormat : Core::uint32 {
};
constexpr Core::uint32 kGaussianSplatSHCoefficientCount = 45;
constexpr Core::uint32 kGaussianSplatSHColorChannelCount = 3;
constexpr Core::uint32 kGaussianSplatMaxSHOrder = 3;
Core::uint32 ResolveGaussianSplatSHOrderFromCoefficientCount(Core::uint32 coefficientCount);
Core::uint32 ResolveGaussianSplatSHOrderFromSectionStride(Core::uint32 elementStride);
struct GaussianSplatPositionRecord {
Math::Vector3 position = Math::Vector3::Zero();
@@ -113,6 +118,7 @@ public:
GaussianSplatSectionFormat GetOtherFormat() const { return m_metadata.otherFormat; }
GaussianSplatSectionFormat GetColorFormat() const { return m_metadata.colorFormat; }
GaussianSplatSectionFormat GetSHFormat() const { return m_metadata.shFormat; }
Core::uint32 GetSHOrder() const;
GaussianSplatSectionFormat GetChunkFormat() const { return m_metadata.chunkFormat; }
GaussianSplatSectionFormat GetCameraFormat() const { return m_metadata.cameraFormat; }
const Containers::Array<GaussianSplatSection>& GetSections() const { return m_sections; }

View File

@@ -1064,6 +1064,11 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
commandList->SetPipelineState(pipelineState);
const float shOrder =
visibleGaussianSplat.gaussianSplat != nullptr
? static_cast<float>(visibleGaussianSplat.gaussianSplat->GetSHOrder())
: 0.0f;
const PerObjectConstants perObjectConstants = {
sceneData.cameraData.projection,
sceneData.cameraData.view,
@@ -1080,7 +1085,7 @@ bool BuiltinGaussianSplatPass::PrepareVisibleGaussianSplat(
Math::Vector4(
static_cast<float>(cachedGaussianSplat->splatCount),
static_cast<float>(workingSet->sortCapacity),
3.0f,
shOrder,
0.0f)
};

View File

@@ -3,6 +3,38 @@
namespace XCEngine {
namespace Resources {
Core::uint32 ResolveGaussianSplatSHOrderFromCoefficientCount(Core::uint32 coefficientCount) {
if (coefficientCount == 0u || (coefficientCount % kGaussianSplatSHColorChannelCount) != 0u) {
return 0u;
}
Core::uint32 remainingTriplets = coefficientCount / kGaussianSplatSHColorChannelCount;
Core::uint32 resolvedOrder = 0u;
for (Core::uint32 order = 1u; order <= kGaussianSplatMaxSHOrder; ++order) {
const Core::uint32 bandTriplets = (2u * order) + 1u;
if (remainingTriplets < bandTriplets) {
break;
}
remainingTriplets -= bandTriplets;
resolvedOrder = order;
}
return resolvedOrder;
}
Core::uint32 ResolveGaussianSplatSHOrderFromSectionStride(Core::uint32 elementStride) {
if (elementStride < sizeof(float)) {
return 0u;
}
const Core::uint32 floatCount = elementStride / static_cast<Core::uint32>(sizeof(float));
const Core::uint32 coefficientCount = floatCount > kGaussianSplatSHCoefficientCount
? kGaussianSplatSHCoefficientCount
: floatCount;
return ResolveGaussianSplatSHOrderFromCoefficientCount(coefficientCount);
}
GaussianSplat::GaussianSplat() = default;
GaussianSplat::~GaussianSplat() = default;
@@ -69,6 +101,11 @@ const GaussianSplatSHRecord* GaussianSplat::GetSHRecords() const {
return static_cast<const GaussianSplatSHRecord*>(GetSectionData(GaussianSplatSectionType::SH));
}
Core::uint32 GaussianSplat::GetSHOrder() const {
const GaussianSplatSection* shSection = FindSection(GaussianSplatSectionType::SH);
return shSection != nullptr ? ResolveGaussianSplatSHOrderFromSectionStride(shSection->elementStride) : 0u;
}
bool GaussianSplat::ValidateSections(const Containers::Array<GaussianSplatSection>& sections,
size_t payloadSize) const {
for (size_t index = 0; index < sections.Size(); ++index) {