GaussianSplats3D

GaussianSplats3D

Three.js驱动的实时3D高斯点渲染引擎

GaussianSplats3D是基于Three.js的3D高斯点渲染引擎,能将2D图像转换为实时交互的3D场景。它支持.ply、.splat和.ksplat格式,集成了WebXR、球谐函数渲染和优化的剔除排序算法。该项目可独立运行或与Three.js场景集成,为3D渲染提供灵活解决方案。GaussianSplats3D适用于Web环境,支持大规模点云渲染,性能优化突出。

Three.js3D Gaussian Splatting渲染器WebGL点云Github开源项目

Three.js的3D高斯散射渲染

这是一个基于Three.js的3D高斯散射实时辐射场渲染的渲染器实现。原项目基于CUDA并需要在本地机器上运行,而我想构建一个可通过网络访问的查看器。

3D场景以类似点云的格式存储,可以实时查看、导航和交互。这个渲染器可以处理INRIA项目生成的.ply文件、标准的.splat文件,或者我自己的自定义.ksplat文件,后者是原始.ply文件的精简压缩版本。

当我开始时,已经有了基于网络的查看器 -- antimatter15的WebGL查看器和cvlab-epfl的WebGPU查看器 -- 但还没有Three.js版本。我以这些版本为起点进行了初步实现,但目前这个项目包含的都是我自己的代码。

亮点

  • 渲染完全通过Three.js完成
  • 代码组织为现代ES模块
  • 内置查看器是自包含的,因此加载和查看场景只需很少的代码
  • 查看器可以导入.ply文件、.splat文件或我的自定义压缩.ksplat文件
  • 用户可以将.ply.splat文件转换为.ksplat文件格式
  • 允许与散射点一起渲染Three.js场景或对象组
  • 内置WebXR支持
  • 支持1级和2级球谐函数以实现视角相关效果
  • 注重优化:
    • 在排序和渲染之前使用自定义八叉树对散射点进行剔除
    • WASM散射点排序:使用WASM SIMD指令在C++中实现
    • 部分GPU加速的散射点排序:使用变换反馈预计算散射点距离

已知问题

  • 散射点排序在CPU上运行 – 最好能找到基于GPU的方法
  • 移动或旋转太快时会出现伪影(由于基于CPU的散射点排序)
  • 移动设备上性能不佳
  • 自定义.ksplat文件格式仍需改进,尤其是压缩方面
  • 默认的基于整数的散射点排序对大型场景效果不佳。在这种情况下,可以将查看器参数integerBasedSort设为false,强制使用较慢的基于浮点数的排序

限制

目前可渲染的散射点数量有限制,主要取决于所需的球谐函数程度。这些限制是:

球谐函数程度最大散射点数
0约 16,000,000
1约 11,000,000
2约 8,000,000

未来的工作将包括优化散射点数据在数据纹理中的打包方式,这将有助于提高这些限制。

未来工作

这仍然是一个进行中的工作!还有几件事需要完成:

  • 改进散射点数据在数据纹理中的打包方式
  • 继续优化基于CPU的散射点排序 - 也许可以尝试某种增量排序?
  • 支持非常大的场景(流式传输分段和LOD)

在线演示

https://projects.markkellogg.org/threejs/demo_gaussian_splats_3d.php

控制

鼠标

  • 左键单击设置焦点
  • 左键单击并拖动可围绕焦点旋转
  • 右键单击并拖动可平移相机和焦点

键盘

  • C 切换网格光标,显示鼠标投影射线与散射点网格的交点

  • I 切换显示调试信息的信息面板:

    • 相机位置
    • 相机焦点/观察点
    • 相机上向量
    • 网格光标位置
    • 当前FPS
    • 渲染器窗口大小
    • 渲染的散射点与总散射点的比例
    • 上次散射点排序持续时间
  • U 切换显示相机控制方向的调试对象。它包括一个代表相机轨道轴的绿色箭头和一个代表相机仰角为0时平面的白色方块。

  • 左箭头 逆时针旋转相机的上向量

  • 右箭头 顺时针旋转相机的上向量

  • P 切换点云模式,每个散射点渲染为填充圆

  • = 增加散射点比例

  • - 减小散射点比例

  • O 切换正交模式

从源代码构建并在本地运行

导航到代码目录并运行

npm install

接下来运行构建。对于Linux和Mac OS系统,运行:

npm run build

对于Windows,我添加了一个Windows兼容版本的构建命令:

npm run build-windows

要在本地查看演示场景,运行

npm run demo

演示将在本地http://127.0.0.1:8080/index.html上可访问。你需要下载演示场景的数据并将它们解压到

<代码目录>/build/demo/assets/data

演示场景数据可在此处获取:https://projects.markkellogg.org/downloads/gaussian_splat_data.zip

作为NPM包安装

如果你不想从源代码构建库,它也可以作为NPM包使用。NPM包不包含源代码仓库中可用的源代码或演示。要安装,运行以下命令:

npm install @mkkellogg/gaussian-splats-3d

基本用法

要运行内置查看器:

import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d'; const viewer = new GaussianSplats3D.Viewer({ 'cameraUp': [0, -1, -0.6], 'initialCameraPosition': [-1, -4, 6], 'initialCameraLookAt': [0, 4, 0] }); viewer.addSplatScene('<.ply、.ksplat或.splat文件的路径>', { 'splatAlphaRemovalThreshold': 5, 'showLoadingUI': true, 'position': [0, 1, 0], 'rotation': [0, 0, 0, 1], 'scale': [1.5, 1.5, 1.5] }) .then(() => { viewer.start(); });

查看器参数

参数用途
cameraUp查看场景的自然"上"向量(仅在使用轨道控制且查看器使用自己的相机时有效)。作为相机将围绕其旋转的轴,用于确定场景相对于相机的方向。
initialCameraPosition相机的初始位置(仅在查看器使用自己的相机时使用)。
initialCameraLookAt相机的初始焦点和相机轨道的中心(仅在查看器使用自己的相机时使用)。

addSplatScene()的参数

参数用途
format强制加载器在加载散射点场景时假定指定的文件格式。这在从没有文件扩展名的URL加载时很有用。有效值在SceneFormat枚举中定义:PlySplatKSplat
splatAlphaRemovalThreshold告诉addSplatScene()忽略任何alpha值小于指定值的散射点(有效范围:0 - 255)。默认为1
showLoadingUI在场景加载时显示加载旋转器和/或加载进度条。默认为true
position场景的位置,作为相对于其默认位置的偏移。默认为[0, 0, 0]
rotation场景的旋转,表示为四元数,默认为[0, 0, 0, 1](单位四元数)。
scale场景的缩放,默认为[1, 1, 1]
progressiveLoad渐进加载场景的散射点数据,并允许在加载散射点时渲染和查看场景。此选项仅对addSplatScene()有效,不适用于addSplatScenes()

Viewer还可以使用addSplatScenes()函数同时加载多个场景:

import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d'; viewer.addSplatScenes([{ 'path': '<第一个.ply、.ksplat或.splat文件的路径>', 'splatAlphaRemovalThreshold': 20 }, { 'path': '<第二个.ply、.ksplat或.splat文件的路径>', 'rotation': [-0.14724434, -0.0761755, 0.1410657, 0.976020], 'scale': [1.5, 1.5, 1.5], 'position': [-3, -2, -3.2] } ]) .then(() => { viewer.start(); });

addSplatScene()addSplatScenes()方法将接受原始的.ply文件、标准的.splat文件和我的自定义.ksplat文件。

集成Three.js场景

如果你希望渲染由查看器处理,可以将你自己的Three.js场景集成到查看器中。只需将Three.js场景对象作为threeScene参数传递给构造函数:

import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d'; import * as THREE from 'three'; const threeScene = new THREE.Scene(); const boxColor = 0xBBBBBB; const boxGeometry = new THREE.BoxGeometry(2, 2, 2); const boxMesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({'color': boxColor})); boxMesh.position.set(3, 2, 2); threeScene.add(boxMesh); const viewer = new GaussianSplats3D.Viewer({ 'threeScene': threeScene, }); viewer.addSplatScene('<.ply、.ksplat或.splat文件的路径>') .then(() => { viewer.start(); });

目前这只适用于写入深度缓冲区的物体(例如标准不透明物体)。支持透明物体将更具挑战性:) <br>

viewer还支持"即插即用"模式。DropInViewer类封装了Viewer,可以像任何其他可渲染对象一样添加到Three.js场景中:

import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d'; import * as THREE from 'three'; const threeScene = new THREE.Scene(); const viewer = new GaussianSplats3D.DropInViewer({ 'gpuAcceleratedSort': true }); viewer.addSplatScenes([{ 'path': '<.ply、.ksplat或.splat文件的路径>' 'splatAlphaRemovalThreshold': 5 }, { 'path': '<.ply、.ksplat或.splat文件的路径>', 'rotation': [0, -0.857, -0.514495, 6.123233995736766e-17], 'scale': [1.5, 1.5, 1.5], 'position': [0, -2, -1.2] } ]); threeScene.add(viewer);
<br>

高级选项

viewer通过构造函数参数允许各种级别的自定义。你可以通过为selfDrivenMode参数传递false来控制何时调用其update()render()方法,然后在你认为合适的时候/地方调用这些方法。你还可以使用自己的相机控制器,以及自己的Three.js RendererCamera实例。以下示例展示了所有这些选项:

import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d'; import * as THREE from 'three'; const renderWidth = 800; const renderHeight = 600; const rootElement = document.createElement('div'); rootElement.style.width = renderWidth + 'px'; rootElement.style.height = renderHeight + 'px'; document.body.appendChild(rootElement); const renderer = new THREE.WebGLRenderer({ antialias: false }); renderer.setSize(renderWidth, renderHeight); rootElement.appendChild(renderer.domElement); const camera = new THREE.PerspectiveCamera(65, renderWidth / renderHeight, 0.1, 500); camera.position.copy(new THREE.Vector3().fromArray([-1, -4, 6])); camera.up = new THREE.Vector3().fromArray([0, -1, -0.6]).normalize(); camera.lookAt(new THREE.Vector3().fromArray([0, 4, -0])); const viewer = new GaussianSplats3D.Viewer({ 'selfDrivenMode': false, 'renderer': renderer, 'camera': camera, 'useBuiltInControls': false, 'ignoreDevicePixelRatio': false, 'gpuAcceleratedSort': true, `enableSIMDInSort`: true, 'sharedMemoryForWorkers': true, 'integerBasedSort': true, 'halfPrecisionCovariancesOnGPU': true, 'dynamicScene': false, 'webXRMode': GaussianSplats3D.WebXRMode.None, 'renderMode': GaussianSplats3D.RenderMode.OnChange, 'sceneRevealMode': GaussianSplats3D.SceneRevealMode.Instant, 'antialiased': false, 'focalAdjustment': 1.0, 'logLevel': GaussianSplats3D.LogLevel.None, 'sphericalHarmonicsDegree': 0, `enableOptionalEffects`: false, `plyInMemoryCompressionLevel`: 2 `freeIntermediateSplatData`: false }); viewer.addSplatScene('<.ply、.ksplat或.splat文件的路径>') .then(() => { requestAnimationFrame(update); });

由于selfDrivenMode为false,开发者需要自行调用Viewer类的update()render()方法:

function update() { requestAnimationFrame(update); viewer.update(); viewer.render(); }

高级Viewer参数 <br>

参数用途
selfDrivenMode如果为false,告诉viewer你将手动调用其update()render()方法。默认为true
renderer向viewer传递Three.js Renderer的实例,否则它将创建自己的实例。默认为undefined
camera向viewer传递Three.js Camera的实例,否则它将创建自己的实例。默认为undefined
useBuiltInControls告诉viewer使用自己的相机控制器。默认为true
ignoreDevicePixelRatio告诉viewer假装设备像素比为1,这可以提高设备像素比较大的设备上的性能,但会略微降低视觉质量。默认为false
gpuAcceleratedSort告诉viewer使用部分GPU加速的方法来排序splats。目前这意味着在GPU上进行splat与相机距离的预计算。建议仅在sharedMemoryForWorkers也为true时将此设置为true。在移动设备上默认为false,其他设备上默认为true
enableSIMDInSort启用SIMD WebAssembly指令用于splat排序。默认为true
sharedMemoryForWorkers告诉viewer通过SharedArrayBuffer使用共享内存来与排序web worker进行数据传输。如果设置为false,建议也将gpuAcceleratedSort设置为false。默认为true
integerBasedSort告诉排序web worker使用相关数据的整数版本来计算splats与相机的距离。由于整数运算比浮点运算更快,这减少了排序时间。但在较大的场景中可能导致整数溢出,因此只应用于小型场景。默认为true
halfPrecisionCovariancesOnGPU告诉viewer在纹理中存储splat协方差数据时使用16位浮点值,而不是32位。默认为false
dynamicScene告诉viewer不要进行任何依赖于场景静态的优化。此外,从viewer的splat网格中检索的所有splat数据默认情况下不会应用其各自的场景变换。
webXRMode告诉viewer是否启用内置的Web VR或Web AR。有效值在WebXRMode枚举中定义:NoneVRAR。默认为None
renderMode控制viewer何时渲染场景。有效值在RenderMode枚举中定义:AlwaysOnChangeNever。默认为Always
sceneRevealMode控制场景加载时使用的淡入效果。有效值在SceneRevealMode枚举中定义:DefaultGradualInstantDefault为渐进加载的场景提供一个漂亮的缓慢淡入效果,为非渐进加载的场景提供快速淡入效果。Gradual将强制所有场景使用缓慢淡入效果。Instant将强制所有加载的场景数据立即可见。
antialiased当为true时,将在渲染过程中执行额外步骤,以解决由于在与训练时明显不同的分辨率下渲染高斯体而导致的伪影。这只适用于使用包含此补偿计算的过程训练的模型。更多详情:https://github.com/nerfstudio-project/gsplat/pull/117, https://github.com/graphdeco-inria/gaussian-splatting/issues/294#issuecomment-1772688093
focalAdjustment用于调整焦距相关计算的非科学参数。对于具有非常小的高斯体和细节的场景,增加此值可以帮助提高视觉质量。默认值为1.0。
logLevel控制台日志的详细程度。默认为GaussianSplats3D.LogLevel.None
sphericalHarmonicsDegree在渲染splats时使用的球谐函数程度(假设splat场景中存在数据)。有效值为0、1或2。默认值为0。
enableOptionalEffects当为true时,允许在渲染过程中使用额外的属性和特性来实现诸如不透明度调整等效果。出于性能考虑,默认为false。这些属性与由dynamicScene参数启用的变换属性(缩放、旋转、位置)是分开的。
plyInMemoryCompressionLevel加载.ply文件进行直接渲染(不导出为.ksplat)时的压缩级别。有效值与.ksplat压缩级别相同(0、1或2)。默认为2。
freeIntermediateSplatData当为true时,将释放解压splat缓冲区后用于填充数据纹理的中间splat数据。这将减少内存使用,但如果需要修改该数据,则需要从splat缓冲区重新填充。默认为false
splatRenderMode确定要启用哪种splat渲染模式。有效值在SplatRenderMode枚举中定义:ThreeDTwoDThreeD是原始/传统模式,TwoD是这里描述的新模式:https://surfsplatting.github.io/
<br> ### 创建KSPLAT文件 要将`.ply`或`.splat`文件转换为精简压缩的`.ksplat`格式,有几种选择。最简单的方法是使用[http://127.0.0.1:8080/index.html](http://127.0.0.1:8080/index.html)主演示页面中的用户界面。如果你想以编程方式进行转换,可以在浏览器中运行以下代码:
import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d'; const compressionLevel = 1; const splatAlphaRemovalThreshold = 5; // 255中的5 const sphericalHarmonicsDegree = 1; GaussianSplats3D.PlyLoader.loadFromURL('<.ply或.splat文件路径>', compressionLevel, splatAlphaRemovalThreshold, sphericalHarmonicsDegree) .then((splatBuffer) => { GaussianSplats3D.KSplatLoader.downloadFile(splatBuffer, 'converted_file.ksplat'); });

上述两种方法都会提示你的浏览器自动开始下载转换后的.ksplat文件。

第三种选择是使用附带的nodejs脚本:

node util/create-ksplat.js [.PLY或.SPLAT文件路径] [输出文件] [压缩级别 = 0] [alpha移除阈值 = 1]

目前支持的compressionLevel值为0120表示不压缩,1表示将缩放、旋转、位置和球谐系数值从32位压缩到16位。21类似,但球谐系数压缩到8位。

<br>

CORS问题和SharedArrayBuffer

默认情况下,Viewer类使用共享内存(通过由SharedArrayBuffer支持的类型化数组)与排序splat的Web Worker通信。这种机制存在潜在的安全问题,详见:https://web.dev/articles/cross-origin-isolation-guide。可以通过在`Viewer`构造函数中为`sharedMemoryForWorkers`参数传递`false`来禁用共享内存,但如果你想保持启用,则需要在加载应用程序时服务器发送的响应中包含几个额外的CORS HTTP头。如果没有设置这些头,你可能会在调试控制台中看到类似以下的错误:

"DOMException: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': SharedArrayBuffer transfer requires self.crossOriginIsolated."

对于本地演示,我创建了一个简单的HTTP服务器(util/server.js)来设置这些头:

response.setHeader("Cross-Origin-Opener-Policy", "same-origin");
response.setHeader("Cross-Origin-Embedder-Policy", "require-corp");

Apache中的CORS

对于Apache,你可以编辑.htaccess文件以允许CORS,添加以下行:

Header add Cross-Origin-Opener-Policy "same-origin"
Header add Cross-Origin-Embedder-Policy "require-corp"

此外,你可能需要要求安全连接到你的服务器,将所有通过http://的访问重定向到https://。在Apache中,可以通过在.htaccess文件中添加以下行来实现:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

Vite中的CORS

对于Vite,一个流行的选择是通过npm安装vite-plugin-cross-origin-isolation插件,然后在vite.config.js文件中添加以下内容:

import { defineConfig } from "vite"; export default defineConfig({ plugins: [ { name: "configure-response-headers", configureServer: (server) => { server.middlewares.use((_req, res, next) => { res.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); next(); }); }, }, ], });

在issue #41中还提到了其他配置Vite来处理这个问题的方法。

编辑推荐精选

TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
蛙蛙写作

蛙蛙写作

AI小说写作助手,一站式润色、改写、扩写

蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。

AI辅助写作AI工具蛙蛙写作AI写作工具学术助手办公助手营销助手AI助手
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

下拉加载更多