










项目主页:https://github.com/sparkjsdev/spark | 文档:https://sparkjs.dev/
版本:v2.1.0 | 许可:MIT | 语言:TypeScript + Rust/WASM | 依赖:three >=0.180.0
@sparkjsdev/spark,README 标题 "An advanced 3D Gaussian Splatting renderer for THREE.js",中文可译作"三维高斯泼溅的先进渲染器")。sparkjsdev。spark-rs)。Spark 是一个深度集成进 three.js 渲染管线的高斯泼溅(Gaussian Splatting / 3DGS)渲染引擎。它的核心目标是:把"用多张照片重建出的三维点云(高斯泼溅)"当作与 mesh 同级的普通 three.js 物体来渲染、变换、编辑、动画,并能在 98%+ 的 WebGL2 设备上(包括低端手机)流畅运行。
高斯泼溅是 2023 年以来席卷三维重建界的表示法——用数百万个带协方差的"高斯_blob"来表示场景,比传统 mesh/NeRF 更轻、更真实。但它不在 WebGL 原生渲染栈内:
Spark 解决的就是"让 3DGS 在浏览器里成为一等公民"这件事。它和 PlayCanvas 的 spark/SuperSplat、gsplat.js 等是同一赛道,但 Spark 的差异化在于:完整的 dyno 着色器图(shader graph)系统——用户可以用 JS 像搭积木一样组合 GPU 着色逻辑,在 GPU 上实时生成/变形/着色泼溅。
.PLY(含压缩)、.SPZ、.SPLAT、.KSPLAT、.SOG、.RAD;>=0.180.0(peerDependency)。rustc/cargo,用于 npm run build:wasm 把 spark-rs 编译成 WASM);支持 WASM 的浏览器用于跑解码/LOD。mkdocs-material(pip install mkdocs-material 或 brew install mkdocs-material)。.github/workflows/ 下 build-dist.yml、ci-linux.yml、ci-windows.yaml、deploy-site.yml)。(a) CDN + importmap(最轻,零构建) —— 官方 Quick Start 示例,直接写一个 index.html:
<style> body {margin: 0;} </style>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.180.0/examples/jsm/",
"@sparkjsdev/spark": "https://sparkjs.dev/releases/spark/2.1.0/spark.module.js"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { SparkRenderer, SplatMesh } from "@sparkjsdev/spark";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, innerWidth/innerHeight, 0.01, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
const spark = new SparkRenderer({ renderer }); // 把 Spark 挂进 three 管线
scene.add(spark);
const butterfly = new SplatMesh({ url: "https://sparkjs.dev/assets/splats/butterfly.spz" });
butterfly.position.set(0, 0, -3);
scene.add(butterfly);
renderer.setAnimationLoop((time) => {
renderer.render(scene, camera);
butterfly.rotation.y += 0.01;
});
</script>
(b) NPM 安装(推荐,用于打包项目)
npm install @sparkjsdev/spark
随后 import { SparkRenderer, SplatMesh } from "@sparkjsdev/spark";,three 作为 peer 依赖自行安装。
(c) 源码开发/贡献
npm install
npm run build:wasm # 先编译 Rust -> WASM(spark-rs)
npm run build # 再构建 Spark 本体(vite 双产物)
# 可选:把远程示例资产下载到本地缓存,离线更快
npm run assets:download
npm start # 启动开发服务器,默认 http://localhost:8080/
排错时:npm run clean(清 dist/node_modules/rust/target + 资产)后重来。
| 脚本 | 作用 |
|---|---|
build:wasm |
node rust/build_wasm.js,把 spark-rs 编译为 spark-rs/pkg 的 WASM + JS glue |
build |
build:production + build:dev(vite 双模式,产出 dist/spark.module.js 与 spark.cjs.js 及 .min 版) |
dev |
构建 dev 版 + vite 热更(onchange 'src/**/*' 监听重编) |
start |
同 dev,跑示例服务器 |
test |
node --loader ts-node/esm --test test/**/*.test.ts |
lint / format |
Biome 检查/格式化(@biomejs/biome) |
build-lod |
cargo run --manifest-path rust/build-lod/Cargo.toml 运行独立的 Rust LOD 离线构建工具 |
assets:download / assets:compress |
下载示例资产 / 把 PLY 压缩成 SPZ |
docs / site:build / site:deploy |
MkDocs 文档站本地预览 / 静态构建 / 部署到 GitHub Pages(sparkjsdev.github.io) |
low/medium/high,见 src/quality 体系,由 enableLod、lodRenderScale 等控制)与动态 LOD 降级保证流畅。npm run build:wasm → rust/build_wasm.js 调用 wasm-pack 风格流程,把 rust/spark-lib 编译为 spark-rs/pkg/*.wasm 与 JS 绑定;npm run build → vite 以 src/index.ts 为入口,配合 vite-plugin-glsl(内联 .glsl)、vite-plugin-dts(生成 dist/types/*.d.ts)、vite-plugin-arraybuffer(内联 WASM 二进制)打包出:
dist/spark.module.js / .min.jsdist/spark.cjs.js / .min.jsdist/types/index.d.tsdist/assets/worker-*.js(离屏 worker 包)。Spark 把自己实现为一个 THREE.Mesh 子类(SparkRenderer extends THREE.Mesh),从而无缝插入 three 的 render() 调用。每帧流程:
renderer.render(scene, camera) 触发 SparkRenderer.onBeforeRender(SparkRenderer.ts)。
autoUpdate,调用 updateInternal → 进入异步 driveSort + driveLod。renderSize、相机近/远平面。SplatAccumulator 的变换矩阵(renderToView…)写进 uniforms。maxStdDev、模糊、LOD 参数、排序纹理 ordering、泼溅数据纹理等。geometry.instanceCount = spark.activeSplats。driveLod,worker 内):
pixelScaleLimit;比对相机位姿是否变化 → lodDirty。SplatMesh,initLodTree 分配 lodId。updateLodTrees → traverseLodTrees 得可见索引 → updateLodIndices 写实例索引纹理(lodInstances 中 texture 为 UI32 索引 DataTexture)。traverseLodTrees 生成 raycastIndices 供射线拾取。driveSort,worker 内):
readbackDepth():用 readRenderTargetPixelsAsync 按层读回深度到 Uint32Array。sortWorker.call("sortSplats32", {numSplats, readback, ordering})(由 Rust/WASM 实现的计数排序)。activeSplats 与排序索引,上传/创建 orderingTexture(RGBA32UI DataTexture,4096×N)。RawShaderMaterial,GLSL3)以 ordering 次序纹理 + 泼溅数据纹理(Packed/Ext)在着色器中 texelFetch 出每个 splat 的 center/scale/quaternion/rgba,计算协方差椭圆并光栅化。renderTarget() 渲到离屏 WebGLRenderTarget(可双缓冲);renderCubeMap/renderEnvMap 借助 CubeCamera + PMREMGenerator 生成环境贴图。SplatMesh/SplatGenerator 持有一个 GsplatGenerator(一个 Dyno 程序:输入 index:int → 输出 gsplat:Gsplat)。objectModifiers/worldModifiers/SplatEdit 注入的 dyno 节点(变换、重着色、SDF 编辑、骨骼等)被 constructGenerator 组合成一条管线。DynoProgram 在构造时把整张节点图编译成 GLSL 源码(graph.compile() → 模板拼接 {{GLOBALS}}/{{STATEMENTS}}),缓存为 RawShaderMaterial。numSplats 会让前后帧失去对应(需重排序);改 generator 会触发 GPU 着色器重编译(首次有可感知卡顿,之后按 identity 缓存)。SplatLoader.load(url) → loadInternal;或用 new SplatMesh({ url }) 自动走加载。getSplatFileType 按魔数/扩展名判定格式(PLY=ply、SPZ=解压后 NGSP、SOG=PKZip 内 meta.json、RAD=RAD0;.splat/.ksplat 只能靠扩展名)。workerPool.withWorker,在 SplatWorker 内调用 loadPackedSplats/loadExtSplats,其中 WASM 解码(Rust spark-rs 的 spz/ply/ksplat/sogs/rad 解码器)返回 {numSplats, packedArray/extArrays, extra, splatEncoding, lodSplats?}。PackedSplats 或 ExtSplats,触发 onLoad。lodSplats 存在,建 LOD 子 PackedSplats 供 driveLod 使用。| 文件 | 作用 |
|---|---|
package.json |
包元数据、依赖(fflate、three peer、spark-rs 本地包)、全部 npm 脚本、ESM/CJS/类型导出矩阵 |
biome.json |
Biome lint/format 配置 |
lefthook.yml |
Git 钩子(提交前 lint/format) |
mkdocs.yml |
文档站配置 |
CHANGELOG.md / LICENSE |
版本变更 / MIT 许可 |
index.html / examples.html |
仓库首页 / 示例入口 |
examples/、docs/ |
示例(40+ 个 HTML demo)与 MkDocs 文档源 |
.github/workflows/ |
CI(Linux/Windows 构建、dist 构建、站点部署) |
src/ —— TypeScript 运行时(核心)入口与渲染:
src/index.ts:公共 API 聚合导出(SparkRenderer、SplatMesh、PackedSplats、ExtSplats、dyno、SplatLoader、XR、controls 等)。src/SparkRenderer.ts:引擎心脏。SparkRenderer extends THREE.Mesh,挂载渲染管线;负责 onBeforeRender 钩子、排序/LOD 驱动、离屏渲、环境贴图、多视点。含大量 SparkRendererOptions(外观/裁剪/排序/动态 LOD/注视点/着色器覆盖等)。src/SparkXr.ts:WebXR 总控(SparkXr)、手部追踪(XrHand、JointEnum、25 关节常量)、JointSplats extends SplatMesh(把 25 个关节渲染成椭球 splat 手),支持 VR/AR。src/controls.ts:SparkControls + FpsMovement(WASD/手柄/XR 移动旋转)+ PointerControls(鼠标拖拽/触摸捏合/双击移动/惯性)。数据与网格:
src/PackedSplats.ts:内存与 GPU 数据封装。每个 splat 精确 16 字节(4×uint32):center(float16×3) + scale(uint8 对数, 范围 e-12~e9) + rgba(uint8×4) + 旋转(轴角八面体征 uint8×3)。提供 pushSplat/getSplat/forEachSplat/ensureSplats、GPU DataArrayTexture(RGBA32UI,4096³ 上限)、DynoPackedSplats(可在着色器动态读)、与 Worker/GPU 的共享格式。src/ExtSplats.ts:扩展格式(float32 中心 + 各向异性协方差),用于需要更高精度或 CovSplat 的场景。src/SplatMesh.ts:场景中的泼溅物体(extends SplatGenerator)。持有 packedSplats/extSplats/paged,构造时按优先级建立数据源;每帧 update(FrameUpdateContext) 写 time/recolor/transform/edits;支持 objectModifiers/worldModifiers/skinning、LOD/分页、射线拾取 raycast、资源释放 dispose。src/SplatGenerator.ts:SplatGenerator extends THREE.Object3D(所有泼溅生成器的基类)。定义 GsplatGenerator/CovSplatGenerator(index→gsplat 的 dyno 程序)、SplatModifier(带缓存地给生成器套修改器)、SplatTransformer/CovSplatTransformer(把 Object3D 的矩阵变成 dyno uniform 变换)、FrameUpdateContext 与 updateVersion() 机制。src/SplatLoader.ts:THREE.Loader 子类,多格式加载器。魔数/扩展名检测(getSplatFileType)、Web Worker 线程池解码、产出 PackedSplats/ExtSplats。注:SPZ/PLY/SOG/RAD 的解码实际由 Worker 内的 Rust/WASM 完成(非纯 JS)。src/SplatWorker.ts:Worker 封装(SplatWorker)+ 池(NewSplatWorkerPool,默认 4 worker)。含 tryExclusive(独占队列,避免长任务被打断)与 call(name, args) 的消息协议;构造时把 WASM_MODULE post 给 worker 完成 WASM 初始化。src/wasm.ts:WASM 胶水。用 Vite 的 ?arraybuffer&base64 内联 spark-rs.wasm,WebAssembly.compile 后 init_wasm({module_or_path}) 实例化,导出 WASM_MODULE Promise 与 isInitialized()。src/defines.ts:全局常量。LN_SCALE_MIN=-12/LN_SCALE_MAX=9(尺度编码范围,改此处须同步 splatDefines.glsl)、SPLAT_TEX_*_BITS=11(2048³ 数组纹理上限,2D 数组纹理可达 8G splats)、WASM_SPLAT_SORT=true、SplatFileType 枚举、SplatEncoding/PackedExtra/ExtExtra 等类型。dyno 着色器图系统(最大创新点):
src/dyno.ts:re-export 桶,聚合 src/dyno/*。src/dyno/base.ts:图模型核心。Dyno<IOTypes, IOTypes>(节点:inTypes/outTypes + generate() 产出 GLSL 片段)、DynoVal(带类型+变量名的边)、DynoBlock(子图,含 visit() 拓扑排序生成 statements)、dyno()/dynoBlock() 工厂、UnaryOp/BinaryOp/TrinaryOp 辅助、Compilation(收集 globals/statements/uniforms/updaters)。src/dyno/program.ts:图→GLSL 编译器。DynoProgram 调 graph.compile() 把节点图编译成 {{GLOBALS}}/{{STATEMENTS}} 模板拼接出的着色器源码,用 WeakMap 缓存 RawShaderMaterial(GLSL3)。DynoProgramTemplate 解析模板三段。src/dyno/splats.ts:splat 专用节点。Gsplat/CovSplat GLSL 结构体定义、readPackedSplat/readExtSplat/readCovSplat(texelFetch + unpack* 解包)、transformGsplat(缩放/旋转/平移/重着色)、splitGsplat/combineGsplat、法线/纹理坐标节点。src/dyno/{math,logic,trig,vecmat,transform,texture,convert,control,uniforms,util,value,types}.ts:标准库节点(加减乘除、比较逻辑、三角函数、向量矩阵、纹理采样、类型转换、uniform 绑定、字面量/值封装、类型定义)。生成器、编辑、修饰、工具:
src/SplatGenerator.ts(见上)/ src/SplatEdit.ts:实时编辑。SplatEditSdf(SPHERE/BOX/ELLIPSOID/CYLINDER/CAPSULE/CONE/PLANE 等形状)、SplatEdit(一次编辑操作,含 SplatEditRgbaBlendMode 的 MULTIPLY/SET_RGB/ADD_RGBA)、SplatEdits(把 SDF+编辑编码进 GPU 纹理,作为标准管线里逐点修改器,GPU 上实时改颜色+位移)。src/SplatSkinning.ts:骨骼双四元数变形(SplatSkinningMode)。src/SplatAccumulator.ts:跨场景累加所有 SplatGenerator 的 gsplat 到单一缓冲,供统一排序渲染。src/SplatGeometry.ts:实例化几何(每实例一个 splat)。src/SplatPager.ts:分页/流式加载(大场景按需取块)。src/Readback.ts:从 GPU 读回像素/深度(排序深度读回、cube targets 读回)。src/SparkPortals.ts:传送门效果(含 DISK_PORTAL_FRAGMENT_SHADER)。src/generators.ts + src/generators/{static,snow}.ts:constructGrid/constructAxes/constructSpherePoints/imageSplats/textSplats 程序化生成泼溅;generators.static/snow 内置生成器。src/modifiers.ts + src/modifiers/{depthColor,normalColor}.ts:SplatModifier 集合与按深度/法线着色修改器。src/splatConstructors.ts:程序化构造泼溅的工具。src/hands.ts:手部关节类型与辅助(与 SparkXr 协同)。src/RgbaArray.ts:RGBA 数组封装(readRgbaArray)。src/shaders.ts + src/shaders/*.glsl:共享 GLSL 片段(splatDefines.glsl、computeUvec4*.glsl 等编码/解码辅助)。src/utils.ts:isMobile/isAndroid/isQuest2/isVisionPro、flipPixels、toHalf/fromHalf、floatToUint8、setPackedSplat/unpackSplat 等底层工具。src/spz.ts:transcodeSpz/writeSpz SPZ 转码与写出。rust/ —— Rust/WASM 核心rust/spark-lib/:被编译成 WASM 的算法库(spark-rs)。lib.rs 聚合模块:
ply/spz/ksplat/sogs/rad/antisplat/csplat/gsplat/tsplat(Gslpat/GsplatArray 数据结构,含 SPZ 量化 roundtrip 测试)。sh_clustering(球谐聚簇)、bhatt_lod、quick_lod、tiny_lod、chunk_tree(分层分块树)。ordering(sortSplats32 计数排序)、symmat3(对称阵)。splat_encode、decoder(流式 ChunkReceiver)。wasm-bindgen 暴露给 JS,供 SplatWorker 调用。rust/spark-rs/:独立的 Rust 消费端 crate(decoder、ext_splats、lod_tree、packed_splats、raycast、sort、transform),README 说明其用途,pkg 被 package.json 以 file:rust/spark-rs/pkg 本地引用。rust/build-lod/:离线 LOD 构建 CLI(main.rs + gpu_sh_clustering.rs),npm run build-lod 触发。rust/build_wasm.js / build_rust_wasm.sh / build_rust_wasm.ps1 / .cargo/config.toml:WASM 构建脚本(跨平台)。scripts/ —— 工程脚本download-assets.js(拉示例资产)、clean-assets.js、compress-to-spz.js(PLY→SPZ)、copy-site-files.js/clean-site-files.js/clean-site.js/serve-site.js/deploy-site.js/rename-assets-to-static.js/replace-urls.js(文档站构建与部署)。
dist/ —— 构建产物ESM/CJS/.min、类型声明(dist/types/*.d.ts,含 dyno/ 子目录完整类型)、worker 包、版本 commit.txt。通过 .gitattributes/git update-index --assume-unchanged dist/* 避免误提交。
SparkRenderer 直接是 THREE.Mesh,SplatMesh 是 Object3D——泼溅与 mesh、灯光、相机、three 生态(OrbitControls、后处理、XR)自然融合。SplatPager 分页 + Rust chunk_tree/sh_clustering LOD,支持超大场景按需加载与多分辨率。dist 体积与 WASM 初始化有成本。three>=0.180.0,锁定较新版本,与旧 three 项目不兼容。readbackDepth 每帧读回深度做 CPU 侧计数排序,理论上存在带宽与延迟开销(作者注释称 JS 与 WASM 排序耗时差异不大,故 WASM_SPLAT_SORT 默认开但影响有限)。DynoProgram 在运行时把图编译成 GLSL(RawShaderMaterial,GLSL3),并用 WeakMap 按程序身份缓存材质、按需重编译。这让"在 GPU 上动态生成/编辑泼溅"从"手写 GLSL"变成"搭积木",是 3DGS 领域少见的可组合 GPU 程序抽象。DataArrayTexture(211×211×2^11,最高 8G splats),兼顾内存、缓存与上限。sh_clustering/bhatt_lod/chunk_tree LOD 聚簇、计数排序全用 Rust 编译成 WASM,在 Worker 内运行,性能与安全性俱佳,且 spark-rs 还能作为独立 Rust crate 复用。SplatAccumulator 把全场景 gsplat 汇成单一缓冲,排序与 LOD 各自在独占 worker(tryExclusive 队列)中异步驱动,主线程零阻塞。SplatEdit 把多个 SDF 形状(球/盒/椭球/圆柱/胶囊/锥/平面)编码进纹理,在 dyno 管线里以 softmax 混合逐点实时改颜色+位移,支持风、火、水、变形等动画,无需回 CPU。SplatSkinning 双四元数骨骼变形;SparkXr + JointSplats 把 WebXR 25 关节追踪渲染成椭球 splat 手,拓展到 VR/AR。textSplats/imageSplats/constructGrid 等程序化生成泼溅,并内置 snow/static 生成器与 depth/normal 着色修改器,开箱即用。renderCubeMap/renderEnvMap/renderTarget,支持多相机同时渲染与 splat 参与环境光照。说明:本解读基于对仓库 README、
package.json、src/全部核心模块(SparkRenderer/PackedSplats/SplatMesh/SplatLoader/SplatWorker/wasm/defines/SplatGenerator/SplatEdit/SparkXr/controls)、src/dyno/*(图模型与 GLSL 编译器)、rust/spark-lib/src/lib.rs模块组织,以及示例/文档/CI 结构的实际抓取,关键结论均锚定在真实代码与文件上。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。