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

在ThreeJS中生成大量方块时如何降低CPU/GPU负载并优化性能?

解决ThreeJS大量方块的性能问题

核心问题分析

你当前的实现为每个方块创建独立的THREE.BoxGeometry、THREE.MeshBasicMaterial和THREE.Mesh,这会产生12000次Draw Call,同时占用大量内存,直接导致加载慢、交互卡顿。下面是针对性的优化方案:


方案一:使用InstancedMesh(推荐)

InstancedMesh允许你用同一个几何体和材质渲染大量重复实例,仅存储每个实例的位置、旋转、缩放和颜色等差异数据,Draw Call直接降到1次,性能提升极其明显。

代码示例

function createPlane() {
  // 只创建一次基础几何体和材质
  const geometry = new THREE.BoxGeometry(1, 1, 0.1);
  const material = new THREE.MeshBasicMaterial({ 
    color: 0xffff00,
    vertexColors: true // 开启顶点颜色支持,用于实例变色
  });

  // 计算实例总数:(77 - (-77) + 1) * (38 - (-38) + 1) = 155 * 77 = 11935
  const instanceCount = 155 * 77;
  const instancedMesh = new THREE.InstancedMesh(geometry, material, instanceCount);
  
  // 存储每个实例的矩阵和颜色
  const matrix = new THREE.Matrix4();
  const color = new THREE.Color(0xffff00);
  let index = 0;

  for (let i = -77; i < 78; i++) {
    for (let j = -38; j < 39; j++) {
      // 设置实例位置
      matrix.setPosition(i, j, 0);
      instancedMesh.setMatrixAt(index, matrix);
      // 设置初始颜色
      instancedMesh.setColorAt(index, color);
      index++;
    }
  }

  scene.add(instancedMesh);
  // 保存实例化网格,方便后续交互修改
  window.instancedPlane = instancedMesh;
}

createPlane();

交互变色优化

修改单个实例颜色时,直接操作InstancedMesh的颜色属性,无需遍历所有Mesh:

// 假设通过触摸逻辑获取到目标实例的索引index
function changeInstanceColor(index, newColor) {
  window.instancedPlane.setColorAt(index, new THREE.Color(newColor));
  window.instancedPlane.instanceColor.needsUpdate = true; // 标记颜色数据需要更新
}

方案二:合并几何体(适合不需要频繁修改单个方块的场景)

如果你的场景不需要频繁修改单个方块,可将所有方块的几何体合并为一个,同样将Draw Call降到1次。

代码示例

function createPlane() {
  const baseGeometry = new THREE.BoxGeometry(1, 1, 0.1);
  const material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
  const mergedGeometry = new THREE.BufferGeometry();
  const geometries = [];

  for (let i = -77; i < 78; i++) {
    for (let j = -38; j < 39; j++) {
      const tempGeo = baseGeometry.clone();
      tempGeo.translate(i, j, 0); // 平移到目标位置
      geometries.push(tempGeo);
    }
  }

  // 合并所有几何体
  mergedGeometry.mergeGeometries(geometries);
  const plane = new THREE.Mesh(mergedGeometry, material);
  scene.add(plane);
}

createPlane();

注意事项

合并后无法单独修改单个方块的材质/颜色,若需要交互变色,需改用顶点颜色(在合并前给每个几何体的顶点设置对应颜色),但实现复杂度比InstancedMesh高。


额外优化建议

  • 避免重复创建资源:无论用哪种方案,都只创建一次基础几何体和材质,复用它们。
  • 交互拾取优化:使用THREE.Raycaster配合InstancedMesh的instanceId属性,直接定位到触摸的目标实例,避免遍历所有物体。
  • 减少不必要精度:BoxGeometry默认分段数为1,已经满足方块需求,无需额外调整。

内容的提问来源于stack exchange,提问作者Raayat Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 09:25:14