React Three Fiber 优化(几何体可重用性)

huangapple go评论58阅读模式
英文:

React Three Fiber Optimization (geometry reusability)

问题

Method 2, where you pass the geometry of each square as a parameter, is better in terms of performance and optimization. While both methods seem to have similar initial geometry counts, Method 2 ensures that only one geometry is used for each square throughout the game. This can be more memory-efficient in the long run compared to Method 1, where each square has its own geometry, leading to an increase in geometries as the player moves.

Method 2 helps in reducing the overall geometry count and can be a better choice for performance and optimization, especially if you observe no significant difference in GPU usage between the two methods.

英文:

I am making a game using React Three Fiber and I need to draw some squares around the canvas in the most optimal way.

I also use R3F-Perf for monitoring.

I have a Square.tsx file that gets imported in a Level.tsx file, which maps through an array containing the positions of the squares and places them inside the canvas.

Method 1

If I return this from Square.tsx

return (
    <>
      <mesh position={squarePosition}>
        <boxGeometry
          args={[squareDimensions.x, squareDimensions.y, squareDimensions.z]}
        />
        <meshStandardMaterial color={squareColor} />
      </mesh>
    </>
  );

and I map in Level.tsx

  const squaresMap = level.squaresMap;
  const Squares = squaresMap.flatMap((row, rowIndex) =>
    row.map(
      (value, columnIndex) =>
        value !== 0 && (
          <Square
            key={`${rowIndex}-${columnIndex}`}
            color={getSquareColor(value)}
            positionX={columnIndex}
            positionY={BOARD_HEIGHT}
            positionZ={rowIndex}
          />
        )
    )
  );

I can see in R3F-Perf that each square has its own geometry (37 geometries in total).

Method 2

If instead I pass the geometry of each square as a parameter, and return this from Square.tsx:

  return (
    <>
      <mesh position={squarePosition} geometry={geometry}>
        <meshStandardMaterial color={squareColor} />
      </mesh>
    </>
  );

And then in Level.tsx I create the geometry and then pass it as I map

  const squareGeometry = new THREE.BoxGeometry(
    BOARD_FACTOR * 0.95,
    0.45,
    BOARD_FACTOR * 0.95
  );

// Other code

  const Squares = squaresMap.flatMap((row, rowIndex) =>
    row.map(
      (value, columnIndex) =>
        value !== 0 && (
          <Square
            key={`${rowIndex}-${columnIndex}`}
            color={getSquareColor(value)}
            positionX={columnIndex}
            positionY={BOARD_HEIGHT}
            positionZ={rowIndex}
            geometry={squareGeometry}
          />
        )
    )
  );

I can see that one geometry is used for each square. (21 geometries in total).

BUT

The geometries in R3F-Perf keep increasing as the player moves. If the player moves by one square, the geometries count increases by 2. And this goes on and on forever. So, initially the geometries count is lower with this method, but then it keeps increasing.

I tried both methods, and I didn't obserbe a difference in performance or GPU usage between them.

So, I would like to ask which for the two methods is better in terms of performance/optimization. Any input more than welcome. Thanks!

答案1

得分: 1

如果您的 squareGeometry 位于组件函数体内,它将在每次重新渲染时重新创建(如果启用了严格模式,则会重新创建两次)。

我建议要么将 squareGeometry 放在组件函数外部(如果不希望它改变),要么使用 useMemo 进行记忆化处理:

useMemo(() => new THREE.BoxGeometry(
    BOARD_FACTOR * 0.95,
    0.45,
    BOARD_FACTOR * 0.95
  ), [BOARD_FACTOR])

(我自己没有测试过)

英文:

If your squareGeometry is inside your component function body it will be remade on each re-rendering (twice if you have strict mode on).

I'd suggest to either have squareGeometry outside of your component function (if it is not expected to change), or use useMemo to memoize:

useMemo(() => new THREE.BoxGeometry(
   BOARD_FACTOR * 0.95,
   0.45,
   BOARD_FACTOR * 0.95
 ), [BOARD_FACTOR])

(have not tested it myself)

答案2

得分: 0

我认为我找到了一个解决方案,不是在Level.tsx文件中创建squareGeometry并将其作为属性传递给Level.tsx文件,而是在Square.tsx文件中创建它,并将其作为属性传递给Square.tsx文件。

这样,所有方块都使用相同的几何体,而随着玩家移动,几何体数量不会增加,因为方块不会被重新渲染。

在我得到其他用户更多意见之前,我不会接受我的答案。

英文:

I think I found a solution, instead of creating the squareGeometry in the Level.tsx file and passing as a prop in the Level.tsx file, I created it in Square.tsx and I passed it as a prop in the Square.tsx file.

In this way, one geometry is used for all squares and the geometry count does not increase as the player moves, as the squares are not getting rerendered.

I will not accept my answer until I have more input from other users.

huangapple
  • 本文由 发表于 2023年6月12日 22:32:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76457681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定