之前网上有很多库虽然能绘制,但是效率低下,接下来我们用threejs和luma webgl库来实现在web端进行高效绘制3DGS。以下示例效果是加载了一份3DGS数据,和一个gltf模型。基本能够满帧绘制,效果视频已发到微信公众号。
实现效果
3DGS介绍
3DGS,即三维高斯溅射技术(3D Gaussian Splashing),是一种先进的三维建模和可视化技术。它主要用于计算机图形学、计算机视觉和相关领域,以实现对三维场景的高效和精确表示。
3D 高斯溅射 (3DGS) 的核心技术是通过数百万个微小的、半透明的椭球体(即“高斯溅射”)来创建和渲染 3D 场景。与依赖多边形或复杂神经网络的传统方法不同,3DGS 利用这些溅射点来表现场景。每个溅射点包含其位置、颜色、大小和透明度的信息。当经过组合后,这些溅射点能高度还原场景的真实感。
Luma介绍
Luma WebGL Library 是一个专为通过 Luma 应用捕获的高保真场景设计的 npm 包,提供了 Gaussian Splatting 技术的 WebGL 实现。它的亮点包括 LumaSplatsWebGL 和集成 Three.js 的 LumaSplatsThree,可以轻松地在现有 3D 框架中加入真实的摄影级元素。
技术分析
Luma WebGL 使用了先进的算法来实现互动渲染。其中 LumaSplatsWebGL 提供了一种高效的 WebGL 渲染方案,而 LumaSplatsThree 则将其无缝融合进 Three.js。此库不仅支持背景移除、场景光照、自定义着色器等功能,还能与 Three.js 的雾效、色调映射等特性协同工作,提供前所未有的视觉体验。
技术应用场景
- 背景移除:创建干净的前景展示,去除不必要的背景元素。
- 场景照明:利用 Luma 引擎捕捉的环境信息,照亮您的三维场景,带来身临其境的感受。
- VR 集成:结合 VR 设备,让观众完全沉浸在互动环境中。
- 高性能渲染:针对大规模实例优化,即使在高分辨率下也能保持流畅。
技术特点
- 易用性:简单安装,快速集成到 Three.js 项目中。
- 兼容性:与 Three.js 紧密合作,充分利用框架特性。
- 灵活性:提供定制化功能,如自定义着色器,满足特定需求。
- 高性能:通过禁用 MSAA 和选择性地开启集成,平衡图像质量和性能。
完整使用代码
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0"> <title>3DGS</title> <style> body { margin:0; padding:0; overflow:hidden; } canvas { filter:brightness(1.1) contrast(90%) saturate(1.2); } </style> </head> <body> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.157.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.157.0/examples/jsm/", "@lumaai/luma-web": "https://unpkg.com/@lumaai/luma-web@0.2.0/dist/library/luma-web.module.js" } } </script> <script type="module"> import { WebGLRenderer, PerspectiveCamera, Scene, AmbientLight, PointLight, AnimationMixer, Clock } from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; import { LumaSplatsThree } from '@lumaai/luma-web'; import { Color, FogExp2 } from 'three'; let renderer = new WebGLRenderer({ antialias: true }); renderer.domElement.style.position = 'absolute'; renderer.domElement.style.width = '100%'; renderer.domElement.style.height = '100%'; document.body.appendChild(renderer.domElement); let camera = new PerspectiveCamera(75, 1, 0.1, 1000); camera.position.z = 4.0; camera.position.y = 1.2; camera.position.x = 1.2; let controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; let scene = new Scene(); scene.fog = new FogExp2(new Color(0xf8f8f8).convertLinearToSRGB(), 0.15); scene.background = scene.fog.color; let mixer; const clock = new Clock(); let splat = new LumaSplatsThree({ source: 'https://lumalabs.ai/capture/286e34aa-ab49-4f60-bb0f-82f38ea2694e' }); scene.add(splat); var light = new AmbientLight(0xffffff); scene.add(light); var pointLight = new PointLight(0xFFFFFF, 1.5, 2000); pointLight.position.set(0, 600, 0); pointLight.castShadow = true; scene.add(pointLight); async function loadGLTFModel() { const loader = new GLTFLoader(); try { const gltf = await loader.loadAsync('assets/model/model2.glb'); const model = gltf.scene; model.position.set(-1.5, -1.3, 0.5); model.scale.set(0.8, 0.8, 0.8); model.rotation.set(0, Math.PI / 2.2, 0); scene.add(model); if (gltf.animations.length > 0) { mixer = new AnimationMixer(model); const action = mixer.clipAction(gltf.animations[0]); action.play(); } } catch (error) { console.error('Error loading GLTF model:', error); } } loadGLTFModel(); function frameLoop() { const delta = clock.getDelta(); if (mixer) { mixer.update(delta); } let canvas = renderer.domElement; let width = canvas.clientWidth; let height = canvas.clientHeight; if (canvas.width !== width || canvas.height !== height) { camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height, false); } controls.update(); renderer.render(scene, camera); } renderer.setAnimationLoop(frameLoop); </script> </body> </html>
复制