前言
假设您正在现有项目中集成这些包,而该项目的构建工具为 Webpack 或 Vite。同时,您对 Three.js 和 React 有一定的了解。如果您发现有任何错误或有更好的方法,请随时留言。
安装
npm install three @types/three @react-three/fiber @react-three/drei @mkkellogg/gaussian-splats-3d
设置两个标头
gaussian-splats-3d内部使用Worker和SharedArrayBuffer(共享内存)。
对于顶级文档,需要设置两个标头来实现你网站的跨源隔离:
- Cross-Origin-Opener-Policy 设置为 same-origin(来保护你的源站点免受攻击)
- Cross-Origin-Embedder-Policy 设置为 require-corp 或 credentialless(保护受害者免受你的源站点的影响)
webpack设置标头
{
"devServer":{
"headers": {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin"
}
}
}
vite设置标头
npm i -D vite-plugin-cross-origin-isolation
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();
});
},
},
],
});
创建一个组件
useViewer.ts
import { useCallback, useEffect } from 'react';
import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d';
import { Scene } from 'three';
interface Options {
scene: Scene;
}
export const useViewer= ({ scene }: Options) => {
const init = useCallback(() => {
const viewer = new GaussianSplats3D.DropInViewer();
viewer.addSplatScenes(
[
{
path: 'assets/bonsai-7k-mini.splat',
splatAlphaRemovalThreshold: 20
}
],
true
);
scene.add(viewer);
}, [scene]);
useEffect(() => {
init();
}, []);
};
import React, { useRef } from 'react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
import { PerspectiveCamera, Scene, Vector3 } from 'three';
import { useViewer } from '@/hooks/useWorkRoom';
function setupCamera() {
const camera = new PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 500);
camera.position.set(0, -4, 0);
camera.lookAt(new Vector3().fromArray([0, 0, 0]));
camera.up = new Vector3().fromArray([0, -1, -0.6]).normalize();
return camera;
}
function setupScene() {
const scene = new Scene();
return scene;
}
export const Dashboard = () => {
const scene = useRef<Scene>(setupScene());
const camera = useRef<PerspectiveCamera>(setupCamera());
useViewer({ scene: scene.current });
return (
<Canvas scene={scene.current} camera={camera.current}>
<OrbitControls />
</Canvas>
);
};
export default Dashboard;