gaussian-splat-lite 1.1.4 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ and this project follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.5] - 2026-09-23
11
+
12
+ ### Changed
13
+
14
+ - WebGL and WebGL2 fallback now draw 128 Splats per instance, matching native WebGPU's quad batching.
15
+
16
+ ### Removed
17
+
18
+ - Removed the `vertexShader`, `fragmentShader`, and `extraUniforms` options from `GaussianSplatRenderer`. All backends use the built-in Splat shaders.
19
+
10
20
  ## [1.1.4] - 2026-09-23
11
21
 
12
22
  ### Changed
@@ -402,7 +412,8 @@ and this project follows [Semantic Versioning](https://semver.org/).
402
412
 
403
413
  - Initial public release of the Three.js Gaussian Splatting renderer.
404
414
 
405
- [Unreleased]: https://github.com/WilliamLiu-1997/Gaussian-Splat-Lite/compare/v1.1.4...HEAD
415
+ [Unreleased]: https://github.com/WilliamLiu-1997/Gaussian-Splat-Lite/compare/v1.1.5...HEAD
416
+ [1.1.5]: https://github.com/WilliamLiu-1997/Gaussian-Splat-Lite/compare/v1.1.4...v1.1.5
406
417
  [1.1.4]: https://github.com/WilliamLiu-1997/Gaussian-Splat-Lite/compare/v1.1.3...v1.1.4
407
418
  [1.1.3]: https://github.com/WilliamLiu-1997/Gaussian-Splat-Lite/compare/v1.1.2...v1.1.3
408
419
  [1.1.2]: https://github.com/WilliamLiu-1997/Gaussian-Splat-Lite/compare/v1.1.1...v1.1.2
@@ -24352,6 +24352,8 @@ function makeSplatUniforms() {
24352
24352
  encodeLinear: { value: false },
24353
24353
  // Mirrors the material flag for WebGPU's output premultiplication.
24354
24354
  premultipliedAlpha: { value: true },
24355
+ // Exact draw count; the final instance may contain unused quads.
24356
+ splatCount: { value: 0 },
24355
24357
  // Back-to-front sort ordering of splat indices
24356
24358
  ordering: { type: "t", value: emptyOrdering },
24357
24359
  // Gsplat collection to render
@@ -24359,10 +24361,6 @@ function makeSplatUniforms() {
24359
24361
  splats2: { type: "t", value: emptySplats },
24360
24362
  stochasticSeeds: { type: "t", value: emptySplats },
24361
24363
  stochasticNoise: { value: createBlueNoiseTexture() },
24362
- // Time in seconds for time-based effects
24363
- time: { value: 0 },
24364
- // Delta time in seconds since last frame
24365
- deltaTime: { value: 0 },
24366
24364
  // Sorting-free stochastic transparency for automatic or forced frames
24367
24365
  stochastic: { value: false },
24368
24366
  // NDC jitter (xy) and blue-noise offset (zw), owned by StochasticTAAPass.
@@ -24456,8 +24454,8 @@ class FullScreenQuad {
24456
24454
  }
24457
24455
  }
24458
24456
  var splatDefines_default = "const uint SPLAT_TEX_WIDTH_BITS = 11u;\nconst uint SPLAT_TEX_HEIGHT_BITS = 11u;\nconst uint SPLAT_TEX_LAYER_BITS = SPLAT_TEX_WIDTH_BITS + SPLAT_TEX_HEIGHT_BITS;\n\nconst uint SPLAT_TEX_WIDTH = 1u << SPLAT_TEX_WIDTH_BITS;\nconst uint SPLAT_TEX_HEIGHT = 1u << SPLAT_TEX_HEIGHT_BITS;\n\nconst uint SPLAT_TEX_WIDTH_MASK = SPLAT_TEX_WIDTH - 1u;\nconst uint SPLAT_TEX_HEIGHT_MASK = SPLAT_TEX_HEIGHT - 1u;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvec3 srgbToLinear(vec3 rgb) {\n \n return mix(\n pow(rgb * 0.9478672986 + vec3(0.0521327014), vec3(2.4)),\n rgb * 0.0773993808, lessThanEqual(rgb, vec3(0.04045)));\n}\n\nuint encodeQuatOctXy1010R12(vec4 q) {\n \n if (q.w < 0.0) {\n q = -q;\n }\n \n float theta = 2.0 * acos(clamp(q.w, 0.0, 1.0));\n\n \n \n \n float sum = abs(q.x) + abs(q.y) + abs(q.z);\n \n vec2 p = (sum < 1e-6) ? vec2(1.0, 0.0) : q.xy / sum;\n \n if (q.z < 0.0) {\n float oldPx = p.x;\n p.x = (1.0 - abs(p.y)) * (p.x >= 0.0 ? 1.0 : -1.0);\n p.y = (1.0 - abs(oldPx)) * (p.y >= 0.0 ? 1.0 : -1.0);\n }\n \n float u_f = p.x * 0.5 + 0.5;\n float v_f = p.y * 0.5 + 0.5;\n \n uint quantU = uint(clamp(round(u_f * 1023.0), 0.0, 1023.0));\n uint quantV = uint(clamp(round(v_f * 1023.0), 0.0, 1023.0));\n \n \n \n uint angleInt = uint(clamp(round((theta / PI) * 4095.0), 0.0, 4095.0));\n \n \n return (angleInt << 20u) | (quantV << 10u) | quantU;\n}\n\nvec4 decodeQuatOctXy1010R12(uint encoded) {\n \n uint quantU = encoded & uint(0x3FFu); \n uint quantV = (encoded >> 10u) & uint(0x3FFu); \n uint angleInt = encoded >> 20u; \n\n \n float u_f = float(quantU) / 1023.0;\n float v_f = float(quantV) / 1023.0;\n vec2 f = vec2(u_f * 2.0 - 1.0, v_f * 2.0 - 1.0);\n\n vec3 axis = vec3(f.xy, 1.0 - abs(f.x) - abs(f.y));\n float t = max(-axis.z, 0.0);\n axis.x += (axis.x >= 0.0) ? -t : t;\n axis.y += (axis.y >= 0.0) ? -t : t;\n axis = normalize(axis);\n \n \n float theta = (float(angleInt) / 4095.0) * PI;\n float halfTheta = theta * 0.5;\n float s = sin(halfTheta);\n float w = cos(halfTheta);\n \n return vec4(axis * s, w);\n}\n\nvec3 decodeSplatCenter(uvec4 splatData) {\n return vec3(\n uintBitsToFloat(splatData.x),\n uintBitsToFloat(splatData.y),\n uintBitsToFloat(splatData.z)\n );\n}\n\nvoid encodeSplatLnScale(\n out uvec4 splatData, out uvec4 splatData2,\n vec3 center, vec3 lnScales, vec4 quaternion, vec4 rgba, float shapeAmount\n) {\n splatData.x = floatBitsToUint(center.x);\n splatData.y = floatBitsToUint(center.y);\n splatData.z = floatBitsToUint(center.z);\n splatData.w = packHalf2x16(clamp(vec2(rgba.a, shapeAmount), 0.0, 1.0));\n\n splatData2.x = packHalf2x16(rgba.rg);\n splatData2.y = packHalf2x16(vec2(rgba.b, lnScales.x));\n splatData2.z = packHalf2x16(lnScales.yz);\n splatData2.w = encodeQuatOctXy1010R12(quaternion);\n}\n\nvec2 decodeSplatAlphaShapeAmount(uvec4 splatData) {\n return unpackHalf2x16(splatData.w);\n}\n\nvoid decodeSplatAttributesLnScale(\n uvec4 splatData2,\n float alpha,\n out vec3 lnScales, out vec4 quaternion, out vec4 rgba\n) {\n rgba.a = alpha;\n\n rgba.rg = unpackHalf2x16(splatData2.x);\n vec2 split = unpackHalf2x16(splatData2.y);\n rgba.b = split.x;\n lnScales.x = split.y;\n lnScales.yz = unpackHalf2x16(splatData2.z);\n quaternion = decodeQuatOctXy1010R12(splatData2.w);\n}\n\nvec3 decodeSplatShRgb(uint encoded) {\n uint biasedBase = (encoded >> 27u) & 0x1fu;\n \n \n float divisor = uintBitsToFloat((biasedBase + 112u) << 23u) / 255.0;\n\n vec3 rgb = vec3(uvec3(encoded & 0xffu, (encoded >> 8u) & 0xffu, (encoded >> 16u) & 0xffu));\n rgb *= divisor;\n\n return vec3(\n ((encoded & 0x1000000u) != 0u) ? -rgb.r : rgb.r,\n ((encoded & 0x2000000u) != 0u) ? -rgb.g : rgb.g,\n ((encoded & 0x4000000u) != 0u) ? -rgb.b : rgb.b\n );\n}\n\nvec3 quatVec(vec4 q, vec3 v) {\n \n vec3 t = 2.0 * cross(q.xyz, v);\n return v + q.w * t + cross(q.xyz, t);\n}\n\nvec4 quatQuat(vec4 q1, vec4 q2) {\n return vec4(\n q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,\n q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x,\n q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w,\n q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n );\n}\n\nmat3 scaleQuaternionToMatrix(vec3 s, vec4 q) {\n \n return mat3(\n s.x * (1.0 - 2.0 * (q.y * q.y + q.z * q.z)),\n s.x * (2.0 * (q.x * q.y + q.w * q.z)),\n s.x * (2.0 * (q.x * q.z - q.w * q.y)),\n s.y * (2.0 * (q.x * q.y - q.w * q.z)),\n s.y * (1.0 - 2.0 * (q.x * q.x + q.z * q.z)),\n s.y * (2.0 * (q.y * q.z + q.w * q.x)),\n s.z * (2.0 * (q.x * q.z + q.w * q.y)),\n s.z * (2.0 * (q.y * q.z - q.w * q.x)),\n s.z * (1.0 - 2.0 * (q.x * q.x + q.y * q.y))\n );\n}\n\nivec3 splatTexCoord(int index) {\n uint x = uint(index) & SPLAT_TEX_WIDTH_MASK;\n uint y = (uint(index) >> SPLAT_TEX_WIDTH_BITS) & SPLAT_TEX_HEIGHT_MASK;\n uint z = uint(index) >> SPLAT_TEX_LAYER_BITS;\n return ivec3(x, y, z);\n}";
24459
- var splatFragment_default = "precision highp float;\nprecision highp int;\n\n#include <splatDefines>\n\nuniform float near;\nuniform float far;\n#ifndef GSL_COLOR_IN_VERTEX\nuniform bool encodeLinear;\n#endif\nuniform float time;\nuniform float minAlpha;\nuniform bool stochastic;\nuniform vec4 stochasticTemporalSample;\nuniform bool stochasticResolve;\nuniform bool depthOnly;\nuniform highp usampler2D stochasticNoise;\nuniform vec2 viewportOrigin;\n\nout vec4 fragColor;\n\nin vec4 vRgba;\nin vec2 vSplatUv;\nflat in uint vStochasticHash;\nflat in float vSupportRadiusSquared;\nflat in float vKernelPower;\n\n#include <logdepthbuf_pars_fragment>\n\nvoid main() {\n vec4 rgba = vRgba;\n\n float z2 = dot(vSplatUv, vSplatUv);\n if (z2 > vSupportRadiusSquared) {\n discard;\n }\n\n float kernelAlpha = exp(-0.5 * z2);\n if (vKernelPower != 0.0) {\n kernelAlpha = 1.0 - pow(1.0 - kernelAlpha, vKernelPower);\n }\n rgba.a *= kernelAlpha;\n\n if (rgba.a < minAlpha) {\n discard;\n }\n #if !GSL_SORTED_FRAGMENT\n if (stochastic || depthOnly) {\n \n uvec2 pixel = uvec2(gl_FragCoord.xy - viewportOrigin);\n uvec2 offset = uvec2(vStochasticHash, vStochasticHash >> 5u);\n if (stochastic && !depthOnly) offset += uvec2(stochasticTemporalSample.zw);\n ivec2 coord = ivec2((pixel + offset) & uvec2(31u));\n float randomValue = (float(texelFetch(stochasticNoise, coord, 0).r) + 0.5) / 1024.0;\n if (randomValue >= rgba.a) {\n discard;\n }\n\n if (depthOnly) {\n fragColor = vec4(0.0);\n #include <logdepthbuf_fragment>\n return;\n }\n }\n #ifndef GSL_COLOR_IN_VERTEX\n if (encodeLinear) {\n rgba.rgb = srgbToLinear(rgba.rgb);\n }\n #endif\n\n if (stochastic) {\n \n \n fragColor = vec4(rgba.rgb, stochasticResolve ? 2.0 : 1.0);\n #include <logdepthbuf_fragment>\n return;\n }\n #endif\n\n #ifdef PREMULTIPLIED_ALPHA\n fragColor = vec4(rgba.rgb * rgba.a, rgba.a);\n #else\n fragColor = rgba;\n #endif\n\n #include <logdepthbuf_fragment>\n}";
24460
- var splatVertex_default = "precision highp float;\nprecision highp int;\nprecision highp usampler2DArray;\n\n#include <splatDefines>\n\nout vec4 vRgba;\nout vec2 vSplatUv;\nflat out uint vStochasticHash;\nflat out float vSupportRadiusSquared;\nflat out float vKernelPower;\n\nuniform vec2 renderSize;\nuniform vec4 renderToViewQuat;\nuniform vec3 renderToViewPos;\n\nuniform float renderToViewScale;\nuniform float maxStdDev;\nuniform float minPixelRadius;\nuniform float maxPixelRadius;\nuniform float time;\nuniform float deltaTime;\nuniform float minAlpha;\nuniform float blurAmount;\nuniform float preBlurAmount;\nuniform float clipXY;\nuniform float focalAdjustment;\nuniform bool stochastic;\nuniform vec4 stochasticTemporalSample;\n#ifdef GSL_COLOR_IN_VERTEX\nuniform bool encodeLinear;\n#endif\nuniform bool depthOnly;\n\nuniform usampler2D ordering;\nuniform usampler2DArray splats;\nuniform usampler2DArray splats2;\nuniform usampler2DArray stochasticSeeds;\n\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == -1.0;\n}\n\n#include <logdepthbuf_pars_vertex>\n\nuint hashU32(uint value) {\n value ^= value >> 16u;\n value *= 0x7feb352du;\n value ^= value >> 15u;\n value *= 0x846ca68bu;\n value ^= value >> 16u;\n return value;\n}\n\nfloat gaussianSupportRadius(float alpha, float maximumRadius) {\n if (minAlpha <= 0.0) return maximumRadius;\n float radiusSquared = 2.0 * log(alpha / minAlpha);\n return min(maximumRadius, sqrt(max(0.0, radiusSquared)));\n}\n\nfloat wideSupportRadius(float alpha, float power, float maximumRadius) {\n if (minAlpha <= 0.0) return maximumRadius;\n \n \n float radiusSquared = 2.0 * log(alpha * power / minAlpha);\n return min(maximumRadius, sqrt(max(0.0, radiusSquared)));\n}\n\nvoid main() {\n \n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n\n uint splatIndex;\n if (stochastic || depthOnly) {\n \n splatIndex = uint(gl_InstanceID);\n } else {\n ivec2 orderingCoord = ivec2((gl_InstanceID >> 2) & 4095, gl_InstanceID >> 14);\n splatIndex = texelFetch(ordering, orderingCoord, 0)[gl_InstanceID & 3];\n }\n if (splatIndex == 0xffffffffu) {\n \n return;\n }\n\n ivec3 texCoord = splatTexCoord(int(splatIndex));\n uvec4 splat1 = texelFetch(splats, texCoord, 0);\n vec2 alphaShapeAmount = decodeSplatAlphaShapeAmount(splat1);\n float alpha = alphaShapeAmount.x;\n if ((alpha == 0.0) || (alpha < minAlpha)) {\n return;\n }\n vec3 center = decodeSplatCenter(splat1);\n \n vec3 viewCenter = renderToViewScale * quatVec(renderToViewQuat, center) + renderToViewPos;\n\n \n if (viewCenter.z >= 0.0) {\n return;\n }\n\n \n vec4 clipCenter = projectionMatrix * vec4(viewCenter, 1.0);\n\n \n if (abs(clipCenter.z) >= clipCenter.w) {\n return;\n }\n\n \n float clip = clipXY * clipCenter.w;\n if (abs(clipCenter.x) > clip || abs(clipCenter.y) > clip) {\n return;\n }\n\n \n \n vec3 lnScales;\n vec4 quaternion, rgba;\n uvec4 splat2 = texelFetch(splats2, texCoord, 0);\n decodeSplatAttributesLnScale(splat2, alpha, lnScales, quaternion, rgba);\n vec3 scales = exp(lnScales);\n if (all(equal(scales, vec3(0.0)))) {\n return;\n }\n\n \n rgba.rgb = max(rgba.rgb, vec3(0.0));\n\n \n \n float kernelShape = 1.0 + 4.0 * min(alphaShapeAmount.y, 1.0);\n \n \n float kernelPower = 0.0;\n if (kernelShape > 1.0) {\n kernelPower = exp(\n (kernelShape * kernelShape - 1.0) / 2.718281828459045\n );\n }\n vKernelPower = kernelPower;\n\n \n float maximumSupportRadius = maxStdDev\n + 0.7 * max(kernelShape - 1.0, 0.0);\n float supportRadius = maximumSupportRadius;\n\n scales *= renderToViewScale;\n\n vRgba = vec4(rgba.rgb, alpha);\n\n \n vec4 viewQuaternion = quatQuat(renderToViewQuat, quaternion);\n\n \n mat3 RS = scaleQuaternionToMatrix(scales, viewQuaternion);\n\n \n vec2 scaledRenderSize = renderSize * focalAdjustment;\n vec2 focal = 0.5 * scaledRenderSize * vec2(projectionMatrix[0][0], projectionMatrix[1][1]);\n\n vec3 j0;\n vec3 j1;\n if (isOrthographic) {\n j0 = vec3(focal.x, 0.0, 0.0);\n j1 = vec3(0.0, focal.y, 0.0);\n } else {\n float invZ = 1.0 / viewCenter.z;\n vec2 J1 = focal * invZ;\n vec2 J2 = -(J1 * viewCenter.xy) * invZ;\n j0 = vec3(J1.x, 0.0, J2.x);\n j1 = vec3(0.0, J1.y, J2.y);\n }\n\n \n \n vec3 p0 = transpose(RS) * j0;\n vec3 p1 = transpose(RS) * j1;\n float a = dot(p0, p0);\n float b = dot(p0, p1);\n float d = dot(p1, p1);\n\n \n a += preBlurAmount;\n d += preBlurAmount;\n\n float detOrig = a * d - b * b;\n \n a += blurAmount;\n d += blurAmount;\n float det = a * d - b * b;\n if (det <= 0.0) return;\n\n \n float blurAdjust = sqrt(max(0.0, detOrig / det));\n alpha *= blurAdjust;\n if (!(alpha > 0.0) || alpha < minAlpha) {\n return;\n }\n vRgba.a = alpha;\n\n \n if (kernelPower == 0.0) {\n supportRadius = gaussianSupportRadius(alpha, supportRadius);\n } else {\n supportRadius = wideSupportRadius(alpha, kernelPower, supportRadius);\n }\n vSupportRadiusSquared = supportRadius * supportRadius;\n vSplatUv = position.xy * supportRadius;\n\n \n float eigenAvg = 0.5 * (a + d);\n float eigenDelta = length(vec2(0.5 * (a - d), b));\n float eigen1 = eigenAvg + eigenDelta;\n \n float eigen2 = max(eigenAvg - eigenDelta, 1e-4);\n\n vec2 eigenVec1 = (abs(b) > 0.001)\n ? normalize(vec2(b, eigen1 - a))\n : ((a >= d) ? vec2(1.0, 0.0) : vec2(0.0, 1.0));\n vec2 eigenVec2 = vec2(eigenVec1.y, -eigenVec1.x);\n\n \n \n float maxProjectedRadius = maxPixelRadius * focalAdjustment;\n float scale1 = min(maxProjectedRadius, maximumSupportRadius * sqrt(eigen1));\n float scale2 = min(maxProjectedRadius, maximumSupportRadius * sqrt(eigen2));\n float supportScale = (maximumSupportRadius > 0.0)\n ? supportRadius / maximumSupportRadius\n : 0.0;\n \n \n float cullScale = (kernelPower == 0.0) ? supportScale : 1.0;\n \n float minProjectedRadius = minPixelRadius * focalAdjustment;\n if (scale1 * cullScale < minProjectedRadius && scale2 * cullScale < minProjectedRadius) {\n return;\n }\n scale1 *= supportScale;\n scale2 *= supportScale;\n\n \n \n vStochasticHash = 0u;\n if (stochastic || depthOnly) {\n vStochasticHash = hashU32(texelFetch(stochasticSeeds, texCoord, 0).r);\n }\n\n \n #ifdef GSL_COLOR_IN_VERTEX\n if (encodeLinear && !depthOnly) {\n vRgba.rgb = srgbToLinear(vRgba.rgb);\n }\n #endif\n\n \n vec2 pixelOffset = position.x * eigenVec1 * scale1 + position.y * eigenVec2 * scale2;\n vec2 ndcOffset = (2.0 / scaledRenderSize) * pixelOffset;\n\n \n vec3 ndcCenter = clipCenter.xyz / clipCenter.w;\n vec3 ndc = vec3(ndcCenter.xy + ndcOffset, ndcCenter.z);\n\n gl_Position = vec4(ndc.xy * clipCenter.w, clipCenter.zw);\n if (stochastic && !depthOnly) {\n gl_Position.xy += stochasticTemporalSample.xy * gl_Position.w;\n }\n\n #include <logdepthbuf_vertex>\n}";
24457
+ var splatFragment_default = "precision highp float;\nprecision highp int;\n\nuniform float minAlpha;\nuniform bool stochastic;\nuniform vec4 stochasticTemporalSample;\nuniform bool stochasticResolve;\nuniform bool depthOnly;\nuniform highp usampler2D stochasticNoise;\nuniform vec2 viewportOrigin;\n\nout vec4 fragColor;\n\nin vec4 vRgba;\nin vec2 vSplatUv;\nflat in uint vStochasticHash;\nflat in float vSupportRadiusSquared;\nflat in float vKernelPower;\n\n#include <logdepthbuf_pars_fragment>\n\nvoid main() {\n vec4 rgba = vRgba;\n\n float z2 = dot(vSplatUv, vSplatUv);\n if (z2 > vSupportRadiusSquared) {\n discard;\n }\n\n float kernelAlpha = exp(-0.5 * z2);\n if (vKernelPower != 0.0) {\n kernelAlpha = 1.0 - pow(1.0 - kernelAlpha, vKernelPower);\n }\n rgba.a *= kernelAlpha;\n\n if (rgba.a < minAlpha) {\n discard;\n }\n #if !GSL_SORTED_FRAGMENT\n if (stochastic || depthOnly) {\n \n uvec2 pixel = uvec2(gl_FragCoord.xy - viewportOrigin);\n uvec2 offset = uvec2(vStochasticHash, vStochasticHash >> 5u);\n if (stochastic && !depthOnly) offset += uvec2(stochasticTemporalSample.zw);\n ivec2 coord = ivec2((pixel + offset) & uvec2(31u));\n float randomValue = (float(texelFetch(stochasticNoise, coord, 0).r) + 0.5) / 1024.0;\n if (randomValue >= rgba.a) {\n discard;\n }\n\n if (depthOnly) {\n fragColor = vec4(0.0);\n #include <logdepthbuf_fragment>\n return;\n }\n }\n if (stochastic) {\n \n \n fragColor = vec4(rgba.rgb, stochasticResolve ? 2.0 : 1.0);\n #include <logdepthbuf_fragment>\n return;\n }\n #endif\n\n #ifdef PREMULTIPLIED_ALPHA\n fragColor = vec4(rgba.rgb * rgba.a, rgba.a);\n #else\n fragColor = rgba;\n #endif\n\n #include <logdepthbuf_fragment>\n}";
24458
+ var splatVertex_default = "precision highp float;\nprecision highp int;\nprecision highp usampler2DArray;\n\n#include <splatDefines>\n\nout vec4 vRgba;\nout vec2 vSplatUv;\nflat out uint vStochasticHash;\nflat out float vSupportRadiusSquared;\nflat out float vKernelPower;\n\nuniform vec2 renderSize;\nuniform vec4 renderToViewQuat;\nuniform vec3 renderToViewPos;\n\nuniform float renderToViewScale;\nuniform float maxStdDev;\nuniform float minPixelRadius;\nuniform float maxPixelRadius;\nuniform float minAlpha;\nuniform float blurAmount;\nuniform float preBlurAmount;\nuniform float clipXY;\nuniform float focalAdjustment;\nuniform bool stochastic;\nuniform vec4 stochasticTemporalSample;\nuniform bool encodeLinear;\nuniform bool depthOnly;\nuniform uint splatCount;\n\nuniform usampler2D ordering;\nuniform usampler2DArray splats;\nuniform usampler2DArray splats2;\nuniform usampler2DArray stochasticSeeds;\n\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == -1.0;\n}\n\n#include <logdepthbuf_pars_vertex>\n\nuint hashU32(uint value) {\n value ^= value >> 16u;\n value *= 0x7feb352du;\n value ^= value >> 15u;\n value *= 0x846ca68bu;\n value ^= value >> 16u;\n return value;\n}\n\nfloat gaussianSupportRadius(float alpha, float maximumRadius) {\n if (minAlpha <= 0.0) return maximumRadius;\n float radiusSquared = 2.0 * log(alpha / minAlpha);\n return min(maximumRadius, sqrt(max(0.0, radiusSquared)));\n}\n\nfloat wideSupportRadius(float alpha, float power, float maximumRadius) {\n if (minAlpha <= 0.0) return maximumRadius;\n \n \n float radiusSquared = 2.0 * log(alpha * power / minAlpha);\n return min(maximumRadius, sqrt(max(0.0, radiusSquared)));\n}\n\nvoid main() {\n \n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n\n uint index = uint(gl_InstanceID) * uint(SPLATS_PER_INSTANCE) + uint(position.z);\n if (index >= splatCount) return;\n\n uint splatIndex;\n if (stochastic || depthOnly) {\n \n splatIndex = index;\n } else {\n ivec2 orderingCoord = ivec2(int((index >> 2u) & 4095u), int(index >> 14u));\n splatIndex = texelFetch(ordering, orderingCoord, 0)[index & 3u];\n }\n if (splatIndex == 0xffffffffu) {\n \n return;\n }\n\n ivec3 texCoord = splatTexCoord(int(splatIndex));\n uvec4 splat1 = texelFetch(splats, texCoord, 0);\n vec2 alphaShapeAmount = decodeSplatAlphaShapeAmount(splat1);\n float alpha = alphaShapeAmount.x;\n if ((alpha == 0.0) || (alpha < minAlpha)) {\n return;\n }\n vec3 center = decodeSplatCenter(splat1);\n \n vec3 viewCenter = renderToViewScale * quatVec(renderToViewQuat, center) + renderToViewPos;\n\n \n if (viewCenter.z >= 0.0) {\n return;\n }\n\n \n vec4 clipCenter = projectionMatrix * vec4(viewCenter, 1.0);\n\n \n if (abs(clipCenter.z) >= clipCenter.w) {\n return;\n }\n\n \n float clip = clipXY * clipCenter.w;\n if (abs(clipCenter.x) > clip || abs(clipCenter.y) > clip) {\n return;\n }\n\n \n \n vec3 lnScales;\n vec4 quaternion, rgba;\n uvec4 splat2 = texelFetch(splats2, texCoord, 0);\n decodeSplatAttributesLnScale(splat2, alpha, lnScales, quaternion, rgba);\n vec3 scales = exp(lnScales);\n if (all(equal(scales, vec3(0.0)))) {\n return;\n }\n\n \n rgba.rgb = max(rgba.rgb, vec3(0.0));\n\n \n \n float kernelShape = 1.0 + 4.0 * min(alphaShapeAmount.y, 1.0);\n \n \n float kernelPower = 0.0;\n if (kernelShape > 1.0) {\n kernelPower = exp(\n (kernelShape * kernelShape - 1.0) / 2.718281828459045\n );\n }\n vKernelPower = kernelPower;\n\n \n float maximumSupportRadius = maxStdDev\n + 0.7 * max(kernelShape - 1.0, 0.0);\n float supportRadius = maximumSupportRadius;\n\n scales *= renderToViewScale;\n\n vRgba = vec4(rgba.rgb, alpha);\n\n \n vec4 viewQuaternion = quatQuat(renderToViewQuat, quaternion);\n\n \n mat3 RS = scaleQuaternionToMatrix(scales, viewQuaternion);\n\n \n vec2 scaledRenderSize = renderSize * focalAdjustment;\n vec2 focal = 0.5 * scaledRenderSize * vec2(projectionMatrix[0][0], projectionMatrix[1][1]);\n\n vec3 j0;\n vec3 j1;\n if (isOrthographic) {\n j0 = vec3(focal.x, 0.0, 0.0);\n j1 = vec3(0.0, focal.y, 0.0);\n } else {\n float invZ = 1.0 / viewCenter.z;\n vec2 J1 = focal * invZ;\n vec2 J2 = -(J1 * viewCenter.xy) * invZ;\n j0 = vec3(J1.x, 0.0, J2.x);\n j1 = vec3(0.0, J1.y, J2.y);\n }\n\n \n \n vec3 p0 = transpose(RS) * j0;\n vec3 p1 = transpose(RS) * j1;\n float a = dot(p0, p0);\n float b = dot(p0, p1);\n float d = dot(p1, p1);\n\n \n a += preBlurAmount;\n d += preBlurAmount;\n\n float detOrig = a * d - b * b;\n \n a += blurAmount;\n d += blurAmount;\n float det = a * d - b * b;\n if (det <= 0.0) return;\n\n \n float blurAdjust = sqrt(max(0.0, detOrig / det));\n alpha *= blurAdjust;\n if (!(alpha > 0.0) || alpha < minAlpha) {\n return;\n }\n vRgba.a = alpha;\n\n \n if (kernelPower == 0.0) {\n supportRadius = gaussianSupportRadius(alpha, supportRadius);\n } else {\n supportRadius = wideSupportRadius(alpha, kernelPower, supportRadius);\n }\n vSupportRadiusSquared = supportRadius * supportRadius;\n vSplatUv = position.xy * supportRadius;\n\n \n float eigenAvg = 0.5 * (a + d);\n float eigenDelta = length(vec2(0.5 * (a - d), b));\n float eigen1 = eigenAvg + eigenDelta;\n \n float eigen2 = max(eigenAvg - eigenDelta, 1e-4);\n\n vec2 eigenVec1 = (abs(b) > 0.001)\n ? normalize(vec2(b, eigen1 - a))\n : ((a >= d) ? vec2(1.0, 0.0) : vec2(0.0, 1.0));\n vec2 eigenVec2 = vec2(eigenVec1.y, -eigenVec1.x);\n\n \n \n float maxProjectedRadius = maxPixelRadius * focalAdjustment;\n float scale1 = min(maxProjectedRadius, maximumSupportRadius * sqrt(eigen1));\n float scale2 = min(maxProjectedRadius, maximumSupportRadius * sqrt(eigen2));\n float supportScale = (maximumSupportRadius > 0.0)\n ? supportRadius / maximumSupportRadius\n : 0.0;\n \n \n float cullScale = (kernelPower == 0.0) ? supportScale : 1.0;\n \n float minProjectedRadius = minPixelRadius * focalAdjustment;\n if (scale1 * cullScale < minProjectedRadius && scale2 * cullScale < minProjectedRadius) {\n return;\n }\n scale1 *= supportScale;\n scale2 *= supportScale;\n\n \n \n vStochasticHash = 0u;\n if (stochastic || depthOnly) {\n vStochasticHash = hashU32(texelFetch(stochasticSeeds, texCoord, 0).r);\n }\n\n \n if (encodeLinear && !depthOnly) {\n vRgba.rgb = srgbToLinear(vRgba.rgb);\n }\n\n \n vec2 pixelOffset = position.x * eigenVec1 * scale1 + position.y * eigenVec2 * scale2;\n vec2 ndcOffset = (2.0 / scaledRenderSize) * pixelOffset;\n\n \n vec3 ndcCenter = clipCenter.xyz / clipCenter.w;\n vec3 ndc = vec3(ndcCenter.xy + ndcOffset, ndcCenter.z);\n\n gl_Position = vec4(ndc.xy * clipCenter.w, clipCenter.zw);\n if (stochastic && !depthOnly) {\n gl_Position.xy += stochasticTemporalSample.xy * gl_Position.w;\n }\n\n #include <logdepthbuf_vertex>\n}";
24461
24459
  let shaders = null;
24462
24460
  function getShaders() {
24463
24461
  if (!shaders) {
@@ -25185,7 +25183,8 @@ class SplatDepthPass {
25185
25183
  ...host.uniforms,
25186
25184
  stochastic: { value: false },
25187
25185
  stochasticResolve: { value: false },
25188
- depthOnly: { value: true }
25186
+ depthOnly: { value: true },
25187
+ splatCount: { value: 0 }
25189
25188
  };
25190
25189
  const material = backend.createDepthMaterial(uniforms);
25191
25190
  material.blending = THREE__namespace.NoBlending;
@@ -25199,9 +25198,9 @@ class SplatDepthPass {
25199
25198
  mesh.onBeforeRender = () => {
25200
25199
  const activeRenderer = this.getActiveRenderer();
25201
25200
  const compiling = backend.kind === "webgpu" && backend.precompile !== null;
25202
- mesh.geometry.setSplatCount(
25203
- compiling || activeRenderer.stochasticActive || activeRenderer.activeSplats === 0 ? 0 : activeRenderer.display.numSplats
25204
- );
25201
+ const splatCount = compiling || activeRenderer.stochasticActive || activeRenderer.activeSplats === 0 ? 0 : activeRenderer.display.numSplats;
25202
+ mesh.geometry.setSplatCount(splatCount);
25203
+ uniforms.splatCount.value = splatCount;
25205
25204
  };
25206
25205
  if (backend.kind === "webgl-fallback") {
25207
25206
  const glBackend = backend.renderer.backend;
@@ -25223,14 +25222,13 @@ class SplatDepthPass {
25223
25222
  this.disposed = true;
25224
25223
  }
25225
25224
  }
25226
- const WEBGPU_SPLATS_PER_INSTANCE = 128;
25225
+ const SPLATS_PER_INSTANCE = 128;
25227
25226
  class SplatGeometry extends THREE__namespace.InstancedBufferGeometry {
25228
- constructor(splatsPerInstance = 1) {
25227
+ constructor() {
25229
25228
  super();
25230
- this.splatsPerInstance = splatsPerInstance;
25231
- const vertices = new Float32Array(splatsPerInstance * 12);
25232
- const indices = new Uint16Array(splatsPerInstance * 6);
25233
- for (let splat = 0; splat < splatsPerInstance; splat++) {
25229
+ const vertices = new Float32Array(SPLATS_PER_INSTANCE * 12);
25230
+ const indices = new Uint16Array(SPLATS_PER_INSTANCE * 6);
25231
+ for (let splat = 0; splat < SPLATS_PER_INSTANCE; splat++) {
25234
25232
  for (let vertex = 0; vertex < 4; vertex++) {
25235
25233
  const offset = splat * 12 + vertex * 3;
25236
25234
  vertices[offset] = QUAD_VERTICES[vertex * 3];
@@ -25244,7 +25242,7 @@ class SplatGeometry extends THREE__namespace.InstancedBufferGeometry {
25244
25242
  this.setIndex(new THREE__namespace.BufferAttribute(indices, 1));
25245
25243
  }
25246
25244
  setSplatCount(count) {
25247
- this.instanceCount = Math.ceil(count / this.splatsPerInstance);
25245
+ this.instanceCount = Math.ceil(count / SPLATS_PER_INSTANCE);
25248
25246
  }
25249
25247
  }
25250
25248
  const QUAD_VERTICES = new Float32Array([
@@ -25758,21 +25756,25 @@ function createSplatNodeMaterial({
25758
25756
  ...view,
25759
25757
  projectionMatrix: N.cameraProjectionMatrix
25760
25758
  });
25761
- const splatIndex = N.uint(N.instanceIndex).toVar();
25762
- N.If(stochastic.or(depthOnly).not(), () => {
25763
- const index2 = N.uint(N.instanceIndex);
25764
- if ("isTextureNode" in orderingNode) {
25765
- const texel = index2.shiftRight(2);
25766
- const coord = N.ivec2(
25767
- texel.mod(ORDERING_TEXTURE_WIDTH),
25768
- texel.div(N.uint(ORDERING_TEXTURE_WIDTH))
25769
- );
25770
- splatIndex.assign(
25771
- load2D(orderingNode, coord).element(index2.bitAnd(3))
25772
- );
25773
- } else {
25774
- splatIndex.assign(orderingNode.element(index2));
25775
- }
25759
+ const index2 = N.uint(N.instanceIndex).mul(SPLATS_PER_INSTANCE).add(N.uint(N.positionGeometry.z)).toVar();
25760
+ const splatIndex = N.uint(4294967295).toVar();
25761
+ const splatCount = uniformBinding(uniforms, "splatCount", "uint");
25762
+ N.If(index2.lessThan(splatCount), () => {
25763
+ splatIndex.assign(index2);
25764
+ N.If(stochastic.or(depthOnly).not(), () => {
25765
+ if ("isTextureNode" in orderingNode) {
25766
+ const texel = index2.shiftRight(2);
25767
+ const coord = N.ivec2(
25768
+ texel.mod(ORDERING_TEXTURE_WIDTH),
25769
+ texel.div(N.uint(ORDERING_TEXTURE_WIDTH))
25770
+ );
25771
+ splatIndex.assign(
25772
+ load2D(orderingNode, coord).element(index2.bitAnd(3))
25773
+ );
25774
+ } else {
25775
+ splatIndex.assign(orderingNode.element(index2));
25776
+ }
25777
+ });
25776
25778
  });
25777
25779
  N.If(splatIndex.notEqual(N.uint(4294967295)), () => {
25778
25780
  const texCoord = splatTexCoord(splatIndex);
@@ -25967,17 +25969,15 @@ class WebGLFallbackSplatBackend extends NodeSplatBackend {
25967
25969
  }
25968
25970
  function createWebGLSplatMaterial(uniforms, options) {
25969
25971
  const shaders2 = getShaders();
25970
- const defines2 = {};
25971
- if (options.vertexShader === void 0 && options.fragmentShader === void 0) {
25972
- defines2.GSL_COLOR_IN_VERTEX = 1;
25973
- defines2.GSL_SORTED_FRAGMENT = 0;
25974
- }
25975
25972
  return new THREE__namespace.ShaderMaterial({
25976
25973
  ...options,
25977
- defines: defines2,
25974
+ defines: {
25975
+ SPLATS_PER_INSTANCE,
25976
+ GSL_SORTED_FRAGMENT: 0
25977
+ },
25978
25978
  glslVersion: THREE__namespace.GLSL3,
25979
- vertexShader: options.vertexShader ?? shaders2.splatVertex,
25980
- fragmentShader: options.fragmentShader ?? shaders2.splatFragment,
25979
+ vertexShader: shaders2.splatVertex,
25980
+ fragmentShader: shaders2.splatFragment,
25981
25981
  uniforms,
25982
25982
  side: THREE__namespace.FrontSide,
25983
25983
  allowOverride: false
@@ -25994,9 +25994,8 @@ class WebGLSplatBackend {
25994
25994
  }
25995
25995
  selectMaterial(useUniform) {
25996
25996
  const { material } = this;
25997
- const currentSorted = material.defines.GSL_SORTED_FRAGMENT;
25998
25997
  const sorted = Number(!useUniform);
25999
- if (currentSorted !== void 0 && currentSorted !== sorted) {
25998
+ if (material.defines.GSL_SORTED_FRAGMENT !== sorted) {
26000
25999
  material.defines.GSL_SORTED_FRAGMENT = sorted;
26001
26000
  material.needsUpdate = true;
26002
26001
  }
@@ -26707,7 +26706,7 @@ class ProjectedSplats {
26707
26706
  this.renderer = renderer;
26708
26707
  this.uniforms = uniforms;
26709
26708
  this.indirect = new IndirectStorageBufferAttribute(
26710
- new Uint32Array([WEBGPU_SPLATS_PER_INSTANCE * 6, 0, 0, 0, 0]),
26709
+ new Uint32Array([SPLATS_PER_INSTANCE * 6, 0, 0, 0, 0]),
26711
26710
  1
26712
26711
  );
26713
26712
  this.error = null;
@@ -26782,7 +26781,7 @@ class ProjectedSplats {
26782
26781
  const index2 = N.uint(N.instanceIndex);
26783
26782
  N.If(index2.equal(0), () => {
26784
26783
  counts.element(viewIndex).assign(count);
26785
- const instances = count.add(WEBGPU_SPLATS_PER_INSTANCE - 1).div(N.uint(WEBGPU_SPLATS_PER_INSTANCE));
26784
+ const instances = count.add(SPLATS_PER_INSTANCE - 1).div(N.uint(SPLATS_PER_INSTANCE));
26786
26785
  drawCount.assign(
26787
26786
  N.select(viewIndex.equal(0), instances, drawCount.max(instances))
26788
26787
  );
@@ -26896,7 +26895,7 @@ class ProjectedSplats {
26896
26895
  const eye = multiView ? N.cameraIndex : N.uint(0);
26897
26896
  const stride = uniformBinding(this.state, "viewStride", "uint");
26898
26897
  const base = eye.mul(stride).toVar();
26899
- const i = N.uint(N.instanceIndex).mul(WEBGPU_SPLATS_PER_INSTANCE).add(N.uint(N.positionGeometry.z));
26898
+ const i = N.uint(N.instanceIndex).mul(SPLATS_PER_INSTANCE).add(N.uint(N.positionGeometry.z));
26900
26899
  const counts = bindBuffer(this.counts).toReadOnly();
26901
26900
  const clipPosition = N.vec4(0, 0, 2, 1).toVar();
26902
26901
  const rgba = N.vec4(0).toVar();
@@ -27142,9 +27141,6 @@ function createSplatBackend(renderer, uniforms, options) {
27142
27141
  if (!isWebGPURenderer(renderer)) {
27143
27142
  return new WebGLSplatBackend(renderer, uniforms, options);
27144
27143
  }
27145
- if (options.vertexShader || options.fragmentShader) {
27146
- throw new Error("Custom GLSL shaders are only supported by WebGLRenderer");
27147
- }
27148
27144
  return usesNativeWebGPU(renderer) ? new WebGPUSplatBackend(renderer, uniforms, options) : new WebGLFallbackSplatBackend(renderer, uniforms, options);
27149
27145
  }
27150
27146
  function configureSplatOutput(renderer, target, uniforms, markerUsers) {
@@ -27224,29 +27220,18 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
27224
27220
  }
27225
27221
  assertSupportedRenderer(options.renderer);
27226
27222
  const uniforms = GaussianSplatRenderer.makeUniforms();
27227
- Object.assign(uniforms, options.extraUniforms);
27228
27223
  const premultipliedAlpha = options.premultipliedAlpha ?? true;
27229
27224
  uniforms.premultipliedAlpha.value = premultipliedAlpha;
27230
27225
  const autoStochastic = options.autoStochastic ?? false;
27231
27226
  const stochastic = options.stochastic ?? false;
27232
27227
  const renderDepth = options.renderDepth ?? false;
27233
- const supportsStochasticShaders = options.vertexShader === void 0 && options.fragmentShader === void 0;
27234
- if ((autoStochastic || stochastic || renderDepth) && !supportsStochasticShaders) {
27235
- throw new Error(
27236
- "Stochastic and renderDepth modes require the built-in Splat shaders"
27237
- );
27238
- }
27239
27228
  const backend = createSplatBackend(options.renderer, uniforms, {
27240
27229
  premultipliedAlpha,
27241
27230
  transparent: options.transparent ?? true,
27242
27231
  depthTest: options.depthTest ?? true,
27243
- depthWrite: options.depthWrite ?? false,
27244
- vertexShader: options.vertexShader,
27245
- fragmentShader: options.fragmentShader
27232
+ depthWrite: options.depthWrite ?? false
27246
27233
  });
27247
- const geometry = new SplatGeometry(
27248
- backend.kind === "webgpu" ? WEBGPU_SPLATS_PER_INSTANCE : 1
27249
- );
27234
+ const geometry = new SplatGeometry();
27250
27235
  const material = backend.selectMaterial(autoStochastic || stochastic);
27251
27236
  super(geometry, material);
27252
27237
  this.renderSize = new THREE__namespace.Vector2();
@@ -27287,7 +27272,6 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
27287
27272
  backend,
27288
27273
  () => GaussianSplatRenderer.gaussianSplatOverride ?? this
27289
27274
  );
27290
- this.supportsStochasticShaders = supportsStochasticShaders;
27291
27275
  this.sortedBlending = material.blending;
27292
27276
  this._depthTest = options.depthTest ?? true;
27293
27277
  this._depthWrite = options.depthWrite ?? false;
@@ -27541,9 +27525,9 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
27541
27525
  const display = gaussianSplatRenderer.display;
27542
27526
  this.uniforms.renderOrigin.value.copy(display.viewOrigin);
27543
27527
  const geometry = this.geometry;
27544
- geometry.setSplatCount(
27545
- gaussianSplatRenderer.stochasticFrame ? display.numSplats : gaussianSplatRenderer.activeSplats
27546
- );
27528
+ const splatCount = gaussianSplatRenderer.stochasticFrame ? display.numSplats : gaussianSplatRenderer.activeSplats;
27529
+ geometry.setSplatCount(splatCount);
27530
+ this.uniforms.splatCount.value = splatCount;
27547
27531
  renderToViewMatrixTmp.copy(camera.matrixWorld).invert().multiply(renderTranslationTmp.makeTranslation(display.viewOrigin)).decompose(
27548
27532
  this.uniforms.renderToViewPos.value,
27549
27533
  this.uniforms.renderToViewQuat.value,
@@ -27568,8 +27552,6 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
27568
27552
  if (this.stochasticModeEnabled) {
27569
27553
  this.applyMaterialState(gaussianSplatRenderer.stochasticFrame);
27570
27554
  }
27571
- this.uniforms.time.value = display.time;
27572
- this.uniforms.deltaTime.value = display.deltaTime;
27573
27555
  if (this.backend.kind === "webgpu") {
27574
27556
  if (this.backend.sortError) throw this.backend.sortError;
27575
27557
  if (this.backend.precompile) {
@@ -27969,13 +27951,6 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
27969
27951
  get depthMesh() {
27970
27952
  return this.depthPass.mesh;
27971
27953
  }
27972
- assertBuiltInSplatShaders(enabled) {
27973
- if (enabled && !this.supportsStochasticShaders) {
27974
- throw new Error(
27975
- "Stochastic and renderDepth modes require the built-in Splat shaders"
27976
- );
27977
- }
27978
- }
27979
27954
  refreshRenderConfiguration() {
27980
27955
  this.applyRenderOrder();
27981
27956
  this.applyMaterialState(this.stochasticFrame);
@@ -28036,7 +28011,6 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
28036
28011
  set autoStochastic(value) {
28037
28012
  const nextValue = Boolean(value);
28038
28013
  if (nextValue === this._autoStochastic) return;
28039
- this.assertBuiltInSplatShaders(nextValue);
28040
28014
  this._autoStochastic = nextValue;
28041
28015
  this.refreshStochasticConfiguration();
28042
28016
  }
@@ -28060,7 +28034,6 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
28060
28034
  set stochastic(value) {
28061
28035
  const nextValue = Boolean(value);
28062
28036
  if (nextValue === this._stochastic) return;
28063
- this.assertBuiltInSplatShaders(nextValue);
28064
28037
  this._stochastic = nextValue;
28065
28038
  this.refreshStochasticConfiguration();
28066
28039
  }
@@ -28070,7 +28043,6 @@ class GaussianSplatRenderer extends THREE__namespace.Mesh {
28070
28043
  set renderDepth(value) {
28071
28044
  const nextValue = Boolean(value);
28072
28045
  if (nextValue === this._renderDepth) return;
28073
- this.assertBuiltInSplatShaders(nextValue);
28074
28046
  this._renderDepth = nextValue;
28075
28047
  this.refreshRenderConfiguration();
28076
28048
  this.setDirty();