mirror of
https://github.com/storytold/spark.git
synced 2026-10-13 23:52:44 +00:00
Custom/extended splat encoding ranges, Premultiplied alpha for hyper-saturated colors (#134)
* Externalized SparkRenderer.maxPixelRadius and .minAlpha settings. Added to documentation. Added to examples/editor under Debug folder, moved sort32 there. * Added SplatEncoding concept, applied individually to SparkRenderer (rgbMin/Max, lnScaleMinMax), SplatMesh (additionally sh1Min/Max, sh2, sh3). Updated examples/editor to control settings via gui. Updated all related code to pipe along settings where needed. Added SparkRenderer.premultipliedAlpha to control blend mode and enable hyper-saturated color contributions by default. * Fix SplatLoader not passing along encoding. Complete renaming to splat encoding.
This commit is contained in:
committed by
GitHub
parent
f4b4522c56
commit
f60c2b0cf9
@@ -1,6 +1,5 @@
|
||||
const float LN_SCALE_MIN = -12.0;
|
||||
const float LN_SCALE_MAX = 9.0;
|
||||
const float LN_RESCALE = (LN_SCALE_MAX - LN_SCALE_MIN) / 254.0; // 1..=255
|
||||
|
||||
const uint SPLAT_TEX_WIDTH_BITS = 11u;
|
||||
const uint SPLAT_TEX_HEIGHT_BITS = 11u;
|
||||
@@ -199,8 +198,13 @@ vec4 decodeQuatOctXy88R8(uint encoded) {
|
||||
// }
|
||||
|
||||
// Pack a Gsplat into a uvec4
|
||||
uvec4 packSplat(vec3 center, vec3 scales, vec4 quaternion, vec4 rgba) {
|
||||
uvec4 uRgba = uvec4(round(clamp(rgba * 255.0, 0.0, 255.0)));
|
||||
uvec4 packSplatEncoding(
|
||||
vec3 center, vec3 scales, vec4 quaternion, vec4 rgba, vec4 rgbMinMaxLnScaleMinMax
|
||||
) {
|
||||
float rgbMin = rgbMinMaxLnScaleMinMax.x;
|
||||
float rgbMax = rgbMinMaxLnScaleMinMax.y;
|
||||
vec3 encRgb = (rgba.rgb - vec3(rgbMin)) / (rgbMax - rgbMin);
|
||||
uvec4 uRgba = uvec4(round(clamp(vec4(encRgb, rgba.a) * 255.0, 0.0, 255.0)));
|
||||
|
||||
uint uQuat = encodeQuatOctXy88R8(quaternion);
|
||||
// uint uQuat = encodeQuatXyz888(quaternion);
|
||||
@@ -208,10 +212,13 @@ uvec4 packSplat(vec3 center, vec3 scales, vec4 quaternion, vec4 rgba) {
|
||||
uvec3 uQuat3 = uvec3(uQuat & 0xffu, (uQuat >> 8u) & 0xffu, (uQuat >> 16u) & 0xffu);
|
||||
|
||||
// Encode scales in three uint8s, where 0=>0.0 and 1..=255 stores log scale
|
||||
float lnScaleMin = rgbMinMaxLnScaleMinMax.z;
|
||||
float lnScaleMax = rgbMinMaxLnScaleMinMax.w;
|
||||
float lnScaleScale = 254.0 / (lnScaleMax - lnScaleMin);
|
||||
uvec3 uScales = uvec3(
|
||||
(scales.x == 0.0) ? 0u : uint(round(clamp((log(scales.x) - LN_SCALE_MIN) / LN_RESCALE, 0.0, 254.0))) + 1u,
|
||||
(scales.y == 0.0) ? 0u : uint(round(clamp((log(scales.y) - LN_SCALE_MIN) / LN_RESCALE, 0.0, 254.0))) + 1u,
|
||||
(scales.z == 0.0) ? 0u : uint(round(clamp((log(scales.z) - LN_SCALE_MIN) / LN_RESCALE, 0.0, 254.0))) + 1u
|
||||
(scales.x == 0.0) ? 0u : uint(round(clamp((log(scales.x) - lnScaleMin) * lnScaleScale, 0.0, 254.0))) + 1u,
|
||||
(scales.y == 0.0) ? 0u : uint(round(clamp((log(scales.y) - lnScaleMin) * lnScaleScale, 0.0, 254.0))) + 1u,
|
||||
(scales.z == 0.0) ? 0u : uint(round(clamp((log(scales.z) - lnScaleMin) * lnScaleScale, 0.0, 254.0))) + 1u
|
||||
);
|
||||
|
||||
// Pack it all into 4 x uint32
|
||||
@@ -222,12 +229,19 @@ uvec4 packSplat(vec3 center, vec3 scales, vec4 quaternion, vec4 rgba) {
|
||||
return uvec4(word0, word1, word2, word3);
|
||||
}
|
||||
|
||||
// Unpack a Gsplat from a uvec4
|
||||
void unpackSplat(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quaternion, out vec4 rgba) {
|
||||
// Pack a Gsplat into a uvec4
|
||||
uvec4 packSplat(vec3 center, vec3 scales, vec4 quaternion, vec4 rgba) {
|
||||
return packSplatEncoding(center, scales, quaternion, rgba, vec4(0.0, 1.0, LN_SCALE_MIN, LN_SCALE_MAX));
|
||||
}
|
||||
|
||||
void unpackSplatEncoding(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quaternion, out vec4 rgba, vec4 rgbMinMaxLnScaleMinMax) {
|
||||
uint word0 = packed.x, word1 = packed.y, word2 = packed.z, word3 = packed.w;
|
||||
|
||||
uvec4 uRgba = uvec4(word0 & 0xffu, (word0 >> 8u) & 0xffu, (word0 >> 16u) & 0xffu, (word0 >> 24u) & 0xffu);
|
||||
rgba = vec4(uRgba) / 255.0;
|
||||
float rgbMin = rgbMinMaxLnScaleMinMax.x;
|
||||
float rgbMax = rgbMinMaxLnScaleMinMax.y;
|
||||
rgba = (vec4(uRgba) / 255.0);
|
||||
rgba.rgb = rgba.rgb * (rgbMax - rgbMin) + rgbMin;
|
||||
|
||||
center = vec4(
|
||||
unpackHalf2x16(word1),
|
||||
@@ -235,10 +249,13 @@ void unpackSplat(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quater
|
||||
).xyz;
|
||||
|
||||
uvec3 uScales = uvec3(word3 & 0xffu, (word3 >> 8u) & 0xffu, (word3 >> 16u) & 0xffu);
|
||||
float lnScaleMin = rgbMinMaxLnScaleMinMax.z;
|
||||
float lnScaleMax = rgbMinMaxLnScaleMinMax.w;
|
||||
float lnScaleScale = (lnScaleMax - lnScaleMin) / 254.0;
|
||||
scales = vec3(
|
||||
(uScales.x == 0u) ? 0.0 : exp(LN_SCALE_MIN + float(uScales.x - 1u) * LN_RESCALE),
|
||||
(uScales.y == 0u) ? 0.0 : exp(LN_SCALE_MIN + float(uScales.y - 1u) * LN_RESCALE),
|
||||
(uScales.z == 0u) ? 0.0 : exp(LN_SCALE_MIN + float(uScales.z - 1u) * LN_RESCALE)
|
||||
(uScales.x == 0u) ? 0.0 : exp(lnScaleMin + float(uScales.x - 1u) * lnScaleScale),
|
||||
(uScales.y == 0u) ? 0.0 : exp(lnScaleMin + float(uScales.y - 1u) * lnScaleScale),
|
||||
(uScales.z == 0u) ? 0.0 : exp(lnScaleMin + float(uScales.z - 1u) * lnScaleScale)
|
||||
);
|
||||
|
||||
|
||||
@@ -248,6 +265,11 @@ void unpackSplat(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quater
|
||||
// quaternion = decodeQuatEulerXyz888(uQuat);
|
||||
}
|
||||
|
||||
// Unpack a Gsplat from a uvec4
|
||||
void unpackSplat(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quaternion, out vec4 rgba) {
|
||||
unpackSplatEncoding(packed, center, scales, quaternion, rgba, vec4(0.0, 1.0, LN_SCALE_MIN, LN_SCALE_MAX));
|
||||
}
|
||||
|
||||
// Rotate vector v by quaternion q
|
||||
vec3 quatVec(vec4 q, vec3 v) {
|
||||
// Rotate vector v by quaternion q
|
||||
|
||||
@@ -6,6 +6,7 @@ precision highp int;
|
||||
|
||||
uniform float near;
|
||||
uniform float far;
|
||||
uniform bool premultipliedAlpha;
|
||||
uniform bool encodeLinear;
|
||||
uniform float maxStdDev;
|
||||
uniform float minAlpha;
|
||||
@@ -67,5 +68,10 @@ void main() {
|
||||
if (encodeLinear) {
|
||||
rgba.rgb = srgbToLinear(rgba.rgb);
|
||||
}
|
||||
fragColor = rgba;
|
||||
|
||||
if (premultipliedAlpha) {
|
||||
fragColor = vec4(rgba.rgb * rgba.a, rgba.a);
|
||||
} else {
|
||||
fragColor = rgba;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ uniform float clipXY;
|
||||
uniform float focalAdjustment;
|
||||
|
||||
uniform usampler2DArray packedSplats;
|
||||
uniform vec4 rgbMinMaxLnScaleMinMax;
|
||||
|
||||
void main() {
|
||||
// Default to outside the frustum so it's discarded if we return early
|
||||
@@ -52,7 +53,7 @@ void main() {
|
||||
|
||||
vec3 center, scales;
|
||||
vec4 quaternion, rgba;
|
||||
unpackSplat(packed, center, scales, quaternion, rgba);
|
||||
unpackSplatEncoding(packed, center, scales, quaternion, rgba, rgbMinMaxLnScaleMinMax);
|
||||
|
||||
if (rgba.a < minAlpha) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user