Files
XCEngine/MVS/3DGS-Unity/Shaders/RenderGaussianSplats.shader
2026-03-29 01:36:53 +08:00

112 lines
2.3 KiB
GLSL

// SPDX-License-Identifier: MIT
Shader "Gaussian Splatting/Render Splats"
{
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Pass
{
ZWrite Off
Blend OneMinusDstAlpha One
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma require compute
#pragma use_dxc
#include "GaussianSplatting.hlsl"
StructuredBuffer<uint> _OrderBuffer;
struct v2f
{
half4 col : COLOR0;
float2 pos : TEXCOORD0;
float4 vertex : SV_POSITION;
};
StructuredBuffer<SplatViewData> _SplatViewData;
ByteAddressBuffer _SplatSelectedBits;
uint _SplatBitsValid;
v2f vert (uint vtxID : SV_VertexID, uint instID : SV_InstanceID)
{
v2f o = (v2f)0;
instID = _OrderBuffer[instID];
SplatViewData view = _SplatViewData[instID];
float4 centerClipPos = view.pos;
bool behindCam = centerClipPos.w <= 0;
if (behindCam)
{
o.vertex = asfloat(0x7fc00000); // NaN discards the primitive
}
else
{
o.col.r = f16tof32(view.color.x >> 16);
o.col.g = f16tof32(view.color.x);
o.col.b = f16tof32(view.color.y >> 16);
o.col.a = f16tof32(view.color.y);
uint idx = vtxID;
float2 quadPos = float2(idx&1, (idx>>1)&1) * 2.0 - 1.0;
quadPos *= 2;
o.pos = quadPos;
float2 deltaScreenPos = (quadPos.x * view.axis1 + quadPos.y * view.axis2) * 2 / _ScreenParams.xy;
o.vertex = centerClipPos;
o.vertex.xy += deltaScreenPos * centerClipPos.w;
// is this splat selected?
if (_SplatBitsValid)
{
uint wordIdx = instID / 32;
uint bitIdx = instID & 31;
uint selVal = _SplatSelectedBits.Load(wordIdx * 4);
if (selVal & (1 << bitIdx))
{
o.col.a = -1;
}
}
}
return o;
}
half4 frag (v2f i) : SV_Target
{
float power = -dot(i.pos, i.pos);
half alpha = exp(power);
if (i.col.a >= 0)
{
alpha = saturate(alpha * i.col.a);
}
else
{
// "selected" splat: magenta outline, increase opacity, magenta tint
half3 selectedColor = half3(1,0,1);
if (alpha > 7.0/255.0)
{
if (alpha < 10.0/255.0)
{
alpha = 1;
i.col.rgb = selectedColor;
}
alpha = saturate(alpha + 0.3);
}
i.col.rgb = lerp(i.col.rgb, selectedColor, 0.5);
}
if (alpha < 1.0/255.0)
discard;
half4 res = half4(i.col.rgb * alpha, alpha);
return res;
}
ENDCG
}
}
}