扩展性能
React Three Fiber 扩展性能
运行
按需渲染

你需要做的就是把
<Canvas frameloop="demand">
一个主要的注意事项是,如果树中的任何东西突变了道具,那么
function Controls() {
const ref = useRef()
const { invalidate, camera, gl } = useThree()
useEffect(() => {
ref.current.addEventListener('change', invalidate)
return () => ref.current.removeEventListener('change', invalidate)
}, [])
return <orbitControls ref={ref} args={[camera, gl.domElement]} />
一般来说,只要你需要渲染,就可以调用
invalidate();
复用Geometries 与Materials
每个
const red = new THREE.MeshLambertMaterial({ color: "red" })
const sphere = new THREE.SphereGeometry(1, 28, 28)
function Scene() {
return (
<>
<mesh geometry={sphere} material={red} />
<mesh position={[1, 2, 3]} geometry={sphere} material={red} />
如果您在整个组件树中通过

function Shoe(props) {
const { nodes, materials } = useLoader(GLTFLoader, "/shoe.glb")
return (
<group {...props} dispose={null}>
<mesh geometry={nodes.shoe.geometry} material={materials.canvas} />
</group>
)
}
<Shoe position={[1, 2, 3]} />
<Shoe position={[4, 5, 6]} />
Instancing
每个网格都是一个绘制调用,你应该注意你使用了多少个这样的调用:最多不超过
function Instances({ count = 100000, temp = new THREE.Object3D() }) {
const ref = useRef();
useEffect(() => {
// Set positions
for (let i = 0; i < count; i++) {
temp.position.set(Math.random(), Math.random(), Math.random());
temp.updateMatrix();
ref.current.setMatrixAt(i, temp.matrix);
}
// Update the instance
ref.current.instanceMatrix.needsUpdate = true;
}, []);
return (
<instancedMesh ref={ref} args={[null, null, count]}>
<boxGeometry />
<meshPhongMaterial />
</instancedMesh>
);
}
Level of detail
有时,物体离相机越远,降低其质量是有益的。如果它几乎不可见,你为什么要全分辨率显示它。这可能是一个很好的策略,可以减少整个顶点数量,这意味着

在
import { Detailed, useGLTF } from '@react-three/drei'
function Model() {
const [low, mid, high] = useGLTF(["/low.glb", "/mid.glb", "/high.glb"])
return (
<Detailed distances={[0, 10, 20]}>
<mesh geometry={high} />
<mesh geometry={mid} />
<mesh geometry={low} />
<Detailed/>
)
}
Nested loading
嵌套式加载意味着较小的纹理和模型首先被加载,较高的分辨率在后面。下面的沙盒经历了三个加载阶段。
- 一个加载指示器
- 低质量
- 高质量

function App() {
return (
<Suspense fallback={<span>loading...</span>}>
<Canvas>
<Suspense fallback={<Model url="/low-quality.glb" />}>
<Model url="/high-quality.glb" />
</Suspense>
</Canvas>
</Suspense>
);
}
function Model({ url }) {
const { scene } = useGLTF(url);
return <primitive object={scene} />;
}
Performance Monitoring
一个调节分辨率的简单例子。一开始是
function App() {
const [dpr, setDpr] = useState(1.5)
return (
<Canvas dpr={dpr}>
<PerformanceMonitor onIncline={() => setDpr(2)} onDecline={() => setDpr(1)} >
你也可以使用
import round from 'lodash/round'
const [dpr, set] = useState(1)
return (
<Canvas dpr={dpr}>
<PerformanceMonitor onChange={({ factor }) => setDpr(round(0.5 + 1.5 * factor, 1))}>
如果你仍然遇到翻转,尽管有界限,你可以定义一个翻转的限制。如果它被满足,
<PerformanceMonitor flipflops={3} onFallback={() => setDpr(1)}>
<PerformanceMonitor>
<Effects />
</PerformanceMonitor>;
function Effects() {
usePerformanceMonitor({ onIncline, onDecline, onFallback, onChange });
// ...
}