рендеринг 1 миллиона коробок в react-три/волокно

#reactjs #three.js #webgl #react-three-fiber

Вопрос:

Я тестирую рендеринг 1 млн коробок в react-three/fiber. Производительность очень низкая.

 function App() {
  const boxes = [];

  for (let i = 0; i < 1000; i  ) {
    const x = Math.random();
    const y = Math.random();
    const z = Math.random();

    const box = (
      <mesh position={[x, y, z]}>
        <boxGeometry args={[0.01, 0.01, 0.01]} />
        <meshLambertMaterial color={"red"} />
      </mesh>
    );

    boxes.push(box);
  }

  return (
    <MBox style={{ height: "100vh", width: "100vw" }}>
      <Canvas camera={{ position: [10, 10, 10] }}>
        <pointLight position={[15, 15, 15]} />
        {boxes}
        <OrbitControls />
        <Stats />
      </Canvas>
    </MBox>
  );
}
 

введите описание изображения здесь

Рендеринг реагирует на 1000 блоков (60 кадров в секунду). С 10000 коробками он падает до 7 кадров в секунду с небольшим недостатком. Браузер умирает со 100000 коробками.

Компьютер, выделенный графическим процессором NVIDIA, вообще не используется. введите описание изображения здесь

Есть какие-нибудь идеи по улучшению производительности, пожалуйста?

Комментарии:

1. Вам следует подумать о том, чтобы визуализировать свои коробки с помощью InstancedMesh .

2. Не уверен, что все еще могу использовать InstancedMesh, если в моем случае каждая коробка будет иметь разную ширину, высоту, глубину.

3. Это может быть реализовано в разных масштабах.

Ответ №1:

Заставил его работать с советами @Mugen87.

 function Boxes() {
  const meshRef = useRef<InstancedMesh>();
  const tempObject = new Object3D();

  useEffect(() => {
    if (meshRef == null) return;
    if (meshRef.current == null) return;

    let i = 0;
    for (let x = 0; x < 100; x  )
      for (let y = 0; y < 100; y  )
        for (let z = 0; z < 100; z  ) {
          const id = i  ;
          tempObject.position.set(x, y, z);
          tempObject.scale.set(1, 0.5, 1.5);
          tempObject.updateMatrix();
          meshRef.current.setMatrixAt(id, tempObject.matrix);
        }
    meshRef.current.instanceMatrix.needsUpdate = true;
  }, []);

  return (
    <instancedMesh ref={meshRef} args={[null as any, null as any, 1000000]}>
      <boxGeometry args={[0.1, 0.1, 0.1]}></boxGeometry>
      <meshBasicMaterial />
    </instancedMesh>
  );
}