Render 3DGS debug splats as quads

This commit is contained in:
2026-04-13 13:38:41 +08:00
parent 8ba05216fb
commit a0d5e84516
3 changed files with 41 additions and 10 deletions

View File

@@ -1,4 +1,19 @@
float4 MainPS(float4 position : SV_Position, float4 color : COLOR0) : SV_Target0 struct PixelInput
{ {
return color; float4 position : SV_Position;
float4 color : COLOR0;
float2 localPosition : TEXCOORD0;
};
float4 MainPS(PixelInput input) : SV_Target0
{
float alpha = exp(-dot(input.localPosition, input.localPosition));
alpha = saturate(alpha * input.color.a);
if (alpha < (1.0 / 255.0))
{
discard;
}
return float4(input.color.rgb * alpha, alpha);
} }

View File

@@ -17,23 +17,34 @@ struct VertexOutput
{ {
float4 position : SV_Position; float4 position : SV_Position;
float4 color : COLOR0; float4 color : COLOR0;
float2 localPosition : TEXCOORD0;
}; };
VertexOutput MainVS(uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID) VertexOutput MainVS(uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID)
{ {
VertexOutput output; VertexOutput output = (VertexOutput)0;
uint splatIndex = gOrderBuffer[instanceId]; uint splatIndex = gOrderBuffer[instanceId];
PreparedSplatView view = gPreparedViews[splatIndex]; PreparedSplatView view = gPreparedViews[splatIndex];
float4 color = UnpackPreparedColor(view); float4 color = UnpackPreparedColor(view);
if (view.clipPosition.w <= 0.0) if (view.clipPosition.w <= 0.0)
{ {
output.position = float4(2.0, 2.0, 2.0, 1.0); const float nanValue = asfloat(0x7fc00000);
output.color = 0.0; output.position = float4(nanValue, nanValue, nanValue, nanValue);
return output; return output;
} }
float2 quadPosition = float2(vertexId & 1, (vertexId >> 1) & 1) * 2.0 - 1.0;
quadPosition *= 2.0;
float2 scaledAxis1 = view.axis1 * gSettings.w;
float2 scaledAxis2 = view.axis2 * gSettings.w;
float2 deltaScreenPosition =
(quadPosition.x * scaledAxis1 + quadPosition.y * scaledAxis2) * 2.0 / gScreenParams.xy;
output.position = view.clipPosition; output.position = view.clipPosition;
output.color = float4(color.rgb, 1.0); output.position.xy += deltaScreenPosition * view.clipPosition.w;
output.color = color;
output.localPosition = quadPosition;
return output; return output;
} }

View File

@@ -209,7 +209,7 @@ FrameConstants BuildFrameConstants(uint32_t width, uint32_t height, uint32_t spl
constants.settings[0] = static_cast<float>(splatCount); constants.settings[0] = static_cast<float>(splatCount);
constants.settings[1] = 1.0f; // opacity scale constants.settings[1] = 1.0f; // opacity scale
constants.settings[2] = 3.0f; // SH order constants.settings[2] = 3.0f; // SH order
constants.settings[3] = 1.0f; constants.settings[3] = 0.9f;
return constants; return constants;
} }
@@ -1108,7 +1108,7 @@ bool App::InitializeDebugDrawResources() {
GraphicsPipelineDesc pipelineDesc = {}; GraphicsPipelineDesc pipelineDesc = {};
pipelineDesc.pipelineLayout = m_debugPipelineLayout; pipelineDesc.pipelineLayout = m_debugPipelineLayout;
pipelineDesc.topologyType = static_cast<uint32_t>(PrimitiveTopologyType::Point); pipelineDesc.topologyType = static_cast<uint32_t>(PrimitiveTopologyType::Triangle);
pipelineDesc.renderTargetCount = 1; pipelineDesc.renderTargetCount = 1;
pipelineDesc.renderTargetFormats[0] = static_cast<uint32_t>(Format::R8G8B8A8_UNorm); pipelineDesc.renderTargetFormats[0] = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
pipelineDesc.depthStencilFormat = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt); pipelineDesc.depthStencilFormat = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt);
@@ -1117,6 +1117,11 @@ bool App::InitializeDebugDrawResources() {
pipelineDesc.rasterizerState.cullMode = static_cast<uint32_t>(CullMode::None); pipelineDesc.rasterizerState.cullMode = static_cast<uint32_t>(CullMode::None);
pipelineDesc.depthStencilState.depthTestEnable = false; pipelineDesc.depthStencilState.depthTestEnable = false;
pipelineDesc.depthStencilState.depthWriteEnable = false; pipelineDesc.depthStencilState.depthWriteEnable = false;
pipelineDesc.blendState.blendEnable = true;
pipelineDesc.blendState.srcBlend = static_cast<uint32_t>(BlendFactor::One);
pipelineDesc.blendState.dstBlend = static_cast<uint32_t>(BlendFactor::InvSrcAlpha);
pipelineDesc.blendState.srcBlendAlpha = static_cast<uint32_t>(BlendFactor::One);
pipelineDesc.blendState.dstBlendAlpha = static_cast<uint32_t>(BlendFactor::InvSrcAlpha);
pipelineDesc.vertexShader.fileName = ResolveShaderPath(L"DebugPointsVS.hlsl").wstring(); pipelineDesc.vertexShader.fileName = ResolveShaderPath(L"DebugPointsVS.hlsl").wstring();
pipelineDesc.vertexShader.entryPoint = L"MainVS"; pipelineDesc.vertexShader.entryPoint = L"MainVS";
@@ -1908,8 +1913,8 @@ void App::RenderFrame(bool captureScreenshot) {
m_commandList.SetPipelineState(m_debugPipelineState); m_commandList.SetPipelineState(m_debugPipelineState);
RHIDescriptorSet* debugSets[] = { m_debugDescriptorSet }; RHIDescriptorSet* debugSets[] = { m_debugDescriptorSet };
m_commandList.SetGraphicsDescriptorSets(0, 1, debugSets, m_debugPipelineLayout); m_commandList.SetGraphicsDescriptorSets(0, 1, debugSets, m_debugPipelineLayout);
m_commandList.SetPrimitiveTopology(PrimitiveTopology::PointList); m_commandList.SetPrimitiveTopology(PrimitiveTopology::TriangleStrip);
m_commandList.Draw(1u, m_gaussianSceneData.splatCount, 0u, 0u); m_commandList.Draw(4u, m_gaussianSceneData.splatCount, 0u, 0u);
if (captureScreenshot) { if (captureScreenshot) {
AppendTrace("RenderFrame: close+execute capture pre-screenshot"); AppendTrace("RenderFrame: close+execute capture pre-screenshot");