You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Three Fiber正方形绘制最优方案咨询(几何复用)

最优方案分析:React Three Fiber 中复用几何的正确姿势

结论

修复方法2中几何数持续增长的问题后,复用单个BoxGeometry的方案是性能最优的,几何复用能从根本上减少GPU内存占用和绘制开销,长期扩展性更好。

两种方案的问题拆解

  • 方法1:每个Square独立创建几何
    即使所有正方形形状完全一致,每个独立的BoxGeometry都会在GPU中存储一份重复的顶点、索引数据。当前37个正方形性能差异不明显,但当数量上升到几百上千时,GPU内存会线性膨胀,还可能引发频繁的垃圾回收,埋下性能隐患。

  • 方法2:共享几何但数量持续增长
    这是异常情况,说明你的代码存在几何重复创建的问题:

    • 可能是Level.tsx中创建几何的逻辑没有用useMemo缓存,导致组件重渲染(比如玩家移动触发状态更新)时每次都新建BoxGeometry;
    • 也可能是Square组件内部没有正确使用传入的几何,反而额外创建了新的实例。

正确的复用实现

1. 在Level.tsx中缓存共享几何

用useMemo确保几何仅初始化一次,不会随组件重渲染重复创建:

import { useMemo } from 'react';
import * as THREE from 'three';

function Level() {
  // 缓存单个BoxGeometry实例
  const sharedBoxGeo = useMemo(() => new THREE.BoxGeometry(1, 1, 1), []);
  // 假设positions是你的位置数组
  const positions = /* 你的位置数据 */;

  return (
    <group>
      {positions.map((pos) => (
        <Square key={pos.id} geometry={sharedBoxGeo} position={pos.coords} />
      ))}
    </group>
  );
}

2. Square.tsx直接使用传入的几何

不要在组件内部创建新的几何,直接复用传入的共享实例:

function Square({ geometry, position }) {
  // 同样建议缓存材质,避免重复创建
  const material = useMemo(() => new THREE.MeshStandardMaterial({ color: '#fff' }), []);

  return (
    <mesh geometry={geometry} material={material} position={position} />
  );
}

这样修改后,R3F-Perf中的几何数会稳定为1(加上场景其他必要几何),不会随玩家移动增长。

进阶优化:InstancedMesh(大量正方形场景)

如果你的正方形数量超过100个,推荐使用<instancedMesh>,它只需要一个网格实例就能渲染所有正方形,性能提升更显著:

function Level() {
  const sharedBoxGeo = useMemo(() => new THREE.BoxGeometry(1, 1, 1), []);
  const sharedMaterial = useMemo(() => new THREE.MeshStandardMaterial({ color: '#fff' }), []);
  const positions = /* 你的位置数据 */;
  const count = positions.length;

  const ref = useRef<THREE.InstancedMesh>(null);

  useEffect(() => {
    if (!ref.current) return;
    // 为每个实例设置位置矩阵
    positions.forEach((pos, index) => {
      const matrix = new THREE.Matrix4().setPosition(pos.x, pos.y, pos.z);
      ref.current.setMatrixAt(index, matrix);
    });
    ref.current.instanceMatrix.needsUpdate = true;
  }, [positions]);

  return (
    <instancedMesh ref={ref} args={[sharedBoxGeo, sharedMaterial, count]} />
  );
}

内容的提问来源于stack exchange,提问作者Michael K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:42:35